|
|
1.1 root 1: /***************************************************************************
2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
3: * is provided to you without charge, and with no warranty. You may give *
4: * away copies of JOVE, including sources, provided that this notice is *
5: * included in all the files. *
6: ***************************************************************************/
7:
8: #include "jove.h"
9: #include "fp.h"
10: #include "ctype.h"
11: #include "termcap.h"
12: #include "disp.h"
13:
14: int AbortCnt,
15: CanScroll = 0,
16: tabstop = 8;
17:
18: #if !(defined(IBMPC) || defined(MAC))
19: private void
20: (*TTins_line) proto((int, int, int)),
21: (*TTdel_line) proto((int, int, int));
22: #endif /* (defined(IBMPC) || defined(MAC)) */
23:
24: struct scrimage
25: *DesiredScreen = 0,
26: *PhysScreen = 0;
27:
28: struct screenline *Screen = 0, /* the screen (a bunch of screenline) */
29: *Curline = 0; /* current line */
30:
31: private struct screenline *Savelines = 0; /* another bunch (LI of them) */
32:
33:
34: private char *cursor; /* offset into current Line */
35:
36: char *cursend;
37:
38: int CapCol,
39: CapLine,
40:
41: i_line,
42: i_col;
43:
44: #ifdef IBMPC
45: extern unsigned char CHPL;
46: extern void near normfun(),
47: near scr_win(),
48: near clr_page(),
49: near clr_eoln();
50:
51: #endif
52:
53: void
54: make_scr()
55: {
56: register int i;
57: register struct screenline *ns;
58: register char *nsp;
59:
60: #ifdef RESHAPING
61: /* In case we are RESHAPING the window! */
62: if (DesiredScreen)
63: free((char *) DesiredScreen);
64: if (PhysScreen)
65: free((char *) PhysScreen);
66: if (Savelines)
67: free((char *) Savelines);
68: if (Screen) {
69: free(Screen->s_line); /* free all the screen data */
70: free((char *) Screen);
71: }
72: #endif /* RESHAPING */
73:
74: DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
75: PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
76:
77: Savelines = (struct screenline *)
78: malloc((unsigned) LI * sizeof(struct screenline));
79: ns = Screen = (struct screenline *)
80: malloc((unsigned) LI * sizeof(struct screenline));
81:
82: nsp = (char *) malloc((unsigned)CO * LI);
83: if (nsp == 0) {
84: writef("\n\rCannot malloc screen!\n");
85: finish(1);
86: }
87:
88: for (i = 0; i < LI; i++) {
89: ns->s_line = nsp;
90: nsp += CO;
91: ns->s_length = nsp - 1; /* End of Line */
92: ns += 1;
93: }
94: cl_scr(0);
95: }
96:
97: void
98: clrline(cp1, cp2)
99: register char *cp1,
100: *cp2;
101: {
102: while (cp1 <= cp2)
103: *cp1++ = ' ';
104: }
105:
106: #if !(defined(IBMPC) || defined(MAC))
107: # define sputc(c) ((*cursor != (char) (c)) ? dosputc((c)) : (cursor++, i_col++))
108: #endif /* (defined(IBMPC) || defined(MAC)) */
109:
110: #ifdef IBMPC
111: int force = 0;
112: # define sputc(c) dosputc((c))
113: #endif /* IBMPC */
114:
115: #ifdef MAC
116: # define sputc(c) bufputc((c)) /* line buffered for mac display */
117: #endif /* MAC */
118:
119: #define soutputc(c) { if (--n <= 0) break; else sputc((c)); }
120:
121: void
122: cl_eol()
123: {
124: if (cursor > cursend)
125: return;
126:
127: if (cursor < Curline->s_length) {
128: #if !(defined(IBMPC) || defined(MAC))
129: if (CE) {
130: #endif /* (defined(IBMPC) || defined(MAC)) */
131: Placur(i_line, i_col);
132: #ifdef TERMCAP
133: putpad(CE, 1);
134: #else
135: clr_eoln();
136: #endif /* TERMCAP */
137: clrline(cursor, Curline->s_length);
138: #if !(defined(IBMPC) || defined(MAC))
139: } else {
140: /* Ugh. The slow way for dumb terminals. */
141: register char *savecp = cursor;
142:
143: while (cursor <= Curline->s_length)
144: sputc(' ');
145: cursor = savecp;
146: }
147: #endif /* (defined(IBMPC) || defined(MAC)) */
148: Curline->s_length = cursor;
149: }
150: }
151:
152: void
153: cl_scr(doit)
154: int doit;
155: {
156: register int i;
157: register struct screenline *sp = Screen;
158:
159: for (i = 0; i < LI; i++, sp++) {
160: clrline(sp->s_line, sp->s_length);
161: sp->s_length = sp->s_line;
162: PhysScreen[i].s_id = 0;
163: }
164: if (doit) {
165: #ifdef TERMCAP
166: putpad(CL, LI);
167: #else
168: clr_page();
169: #endif /* TERMCAP */
170: CapCol = CapLine = 0;
171: UpdMesg = YES;
172: }
173: }
174:
175: /* Output one character (if necessary) at the current position */
176:
177: #ifndef MAC
178: int /* only for lints sake */
179: dosputc(c)
180: register int c;
181: {
182: #ifndef IBMPC
183: if (*cursor != c) {
184: # ifdef ID_CHAR
185: if (IN_INSmode)
186: INSmode(0);
187: # endif
188: #else /* IBMPC */
189: if ((force) || (*cursor != c)) {
190: #endif /* IBMPC */
191: if (i_line != CapLine || i_col != CapCol)
192: Placur(i_line, i_col);
193: #ifndef IBMPC
194: if (UL && (c & CHARMASK) == '_' && (*cursor & CHARMASK) != ' ')
195: putstr(" \b"); /* Erase so '_' looks right. */
196: #endif /* IBMPC */
197: *cursor++ = c;
198: #ifndef IBMPC
199: jputchar(c & CHARMASK);
200: #else /* IBMPC */
201: normfun((char) c);
202: #endif /* IBMPC */
203: AbortCnt -= 1;
204: CapCol += 1;
205: i_col += 1;
206: } else {
207: cursor += 1;
208: i_col += 1;
209: }
210: return 0; /* useless result */
211: }
212: #else /* MAC */
213:
214: /* Character output to bit-mapped screen is very expensive. It makes
215: much more sense to write the entire line at once. So, we print all
216: the characters, whether already there or not, once the line is
217: complete. */
218:
219: #define BUFFLUSH (char) 0
220: #define BUFSTART (char) 1
221:
222: bufputc(c)
223: register char c;
224: {
225: static char buf[256];
226: static int len = 0;
227:
228: if(c == BUFSTART) {
229: /* if (i_line != CapLine || i_col != CapCol)*/
230: NPlacur(i_line, i_col);
231: len = 0;
232: return;
233: }
234: if(c == BUFFLUSH) {
235: buf[0] = (unsigned char) len;
236: writechr(buf);
237: len = 0;
238: }
239: else {
240: if(len > 255) return;
241: *cursor++ = c;
242: if(c == '0') buf[++len] = 0xAF; /* slashed zero */
243: else buf[++len] = c;
244: CapCol++;
245: i_col++;
246: }
247: return;
248: }
249: #endif /* MAC */
250:
251: /* Write `line' at the current position of `cursor'. Stop when we
252: reach the end of the screen. Aborts if there is a character
253: waiting. */
254:
255: #ifdef MAC /* This was getting too complicated with ifdefs ... */
256: int
257: swrite(line, inversep, abortable)
258: register char *line;
259: register int abortable;
260: {
261: register int c;
262: int col = i_col,
263: aborted = 0;
264: register int n = cursend - cursor;
265:
266: if (n <= 0)
267: return 1;
268: sputc(BUFSTART); /* Okay, because no interruption possible */
269:
270: while (c = *line++) {
271: if (abortable && AbortCnt < 0) {
272: AbortCnt = BufSize;
273: if (InputPending = charp()) {
274: aborted = 1;
275: break;
276: }
277: }
278: if (c == '\t') {
279: int nchars;
280:
281: nchars = (tabstop - (col % tabstop));
282: col += nchars;
283:
284: while (nchars--)
285: soutputc(' ');
286: if (n <= 0)
287: break;
288: } else if (isctrl(c)) {
289: soutputc('^');
290: c = ((c == '\177') ? '?' : c + '@');
291: soutputc(c);
292: col += 2;
293: } else {
294: soutputc(c);
295: col += 1;
296: }
297: }
298: if (n <= 0) {
299: if ((*line == '\0') && (c != '\t') && !isctrl(c))
300: sputc(c);
301: sputc('!');
302: }
303: if (cursor > Curline->s_length)
304: Curline->s_length = cursor;
305: sputc(BUFFLUSH);
306: return !aborted;
307: }
308:
309: #else /* MAC */
310:
311: int
312: swrite(line, inversep, abortable)
313: register char *line;
314: int inversep;
315: register int abortable;
316: {
317: register int c;
318: int col = i_col,
319: aborted = 0;
320: register int n = cursend - cursor;
321: #ifndef IBMPC
322: int or_byte = inversep ? 0200 : 0,
323: thebyte;
324: #else
325: int thebyte;
326: #endif /* IBMPC */
327:
328: #ifdef IBMPC
329: force = inversep? 1: 0; /* to force a redraw of the modeline */
330: #endif /* IBMPC */
331:
332: if (n <= 0)
333: return 1;
334: while ((c = *line++) != '\0') {
335: if (abortable && AbortCnt < 0) {
336: AbortCnt = BufSize;
337: if ((InputPending = charp()) != '\0') {
338: aborted = 1;
339: break;
340: }
341: }
342: if (c == '\t') {
343: int nchars;
344:
345: nchars = (tabstop - (col % tabstop));
346: col += nchars;
347:
348: #ifndef IBMPC
349: thebyte = (' ' | or_byte);
350: #endif /* IBMPC */
351: while (nchars--)
352: #ifndef IBMPC
353: soutputc(thebyte);
354: #else /* IBMPC */
355: soutputc(' ');
356: #endif /* IBMPC */
357: if (n <= 0)
358: break;
359: } else if (isctrl(c)) {
360: #ifndef IBMPC
361: thebyte = ('^' | or_byte);
362: soutputc(thebyte);
363: thebyte = (((c == '\177') ? '?' : c + '@') | or_byte);
364: soutputc(thebyte);
365: #else /* IBMPC */
366: soutputc('^');
367: c = ((c == '\177') ? '?' : c + '@');
368: soutputc(c);
369: #endif /* IBMPC */
370: col += 2;
371: #ifdef TERMCAP
372: } else if (HZ && c == '~') {
373: thebyte = ('`' | or_byte);
374: soutputc(thebyte);
375: col += 1;
376: #endif
377: } else {
378: #ifndef IBMPC
379: thebyte = (c | or_byte);
380: soutputc(thebyte);
381: #else /* IBMPC */
382: if (c == 255) c = 1;
383: if (c == ' ' && inversep) c = 255;
384: soutputc(c);
385: #endif /* IBMPC */
386: col += 1;
387: }
388: }
389: if (n <= 0) {
390: if ((*line == '\0') && (c != '\t') && !isctrl(c))
391: #ifndef IBMPC
392: sputc(c|or_byte);
393: #else /* IBMPC */
394: sputc(c);
395: #endif /* IBMPC */
396: else
397: #ifndef IBMPC
398: sputc('!'|or_byte);
399: #else /* IBMPC */
400: sputc('!');
401: #endif /* IBMPC */
402: }
403: if (cursor > Curline->s_length)
404: Curline->s_length = cursor;
405: #ifdef IBMPC
406: force = 0;
407: #endif
408: return !aborted;
409: }
410: #endif /* MAC */
411:
412: /* This is for writing a buffer line to the screen. This is to
413: minimize the amount of copying from one buffer to another buffer.
414: This gets the info directly from the disk buffers. */
415:
416: int
417: BufSwrite(linenum)
418: int linenum;
419: {
420: register int n = cursend - cursor,
421: col = 0,
422: c = -1;
423: register char *bp;
424: int StartCol = DesiredScreen[linenum].s_offset,
425: visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE,
426: aborted = 0;
427:
428: bp = lcontents(DesiredScreen[linenum].s_lp);
429: if (*bp) for (;;) {
430: if (col >= StartCol) {
431: DesiredScreen[linenum].s_offset = col;
432: break;
433: }
434:
435: c = *bp++ & CHARMASK;
436: if (c == '\0')
437: break;
438: if (c == '\t')
439: col += (tabstop - (col % tabstop));
440: else if (isctrl(c))
441: col += 2;
442: else
443: col += 1;
444: }
445: #ifdef MAC
446: sputc(BUFSTART); /* Okay because we can't be interrupted */
447: #endif
448:
449: if (c != '\0') while ((c = *bp++) != '\0') {
450: if (AbortCnt < 0) {
451: AbortCnt = BufSize;
452: if ((InputPending = charp()) != '\0') {
453: aborted = 1;
454: break;
455: }
456: }
457: if (c == '\t') {
458: int nchars = (tabstop - (col % tabstop));
459:
460: col += nchars;
461: if (visspace) {
462: soutputc('>');
463: nchars -= 1;
464: }
465: while (--nchars >= 0)
466: soutputc(' ');
467: if (n <= 0)
468: break;
469: } else if (isctrl(c)) {
470: soutputc('^');
471: soutputc((c == '\177') ? '?' : c + '@');
472: col += 2;
473: #ifdef TERMCAP
474: } else if (HZ && c == '~') {
475: soutputc('`');
476: col += 1;
477: #endif
478: } else {
479: if (c == ' ' && visspace)
480: c = '_';
481: #ifdef IBMPC
482: if (c == 255)
483: c = 1;
484: #endif /* IBMPC */
485: soutputc(c);
486: col += 1;
487: }
488: }
489: if (n <= 0) {
490: if ((*bp == '\0') && (c != '\t') && !isctrl(c))
491: sputc(c);
492: else
493: sputc('!');
494: }
495: if (cursor > Curline->s_length)
496: Curline->s_length = cursor;
497: #ifdef MAC
498: sputc(BUFFLUSH);
499: #endif
500: return !aborted; /* Didn't abort */
501: }
502:
503: void
504: i_set(nline, ncol)
505: register int nline,
506: ncol;
507: {
508: Curline = &Screen[nline];
509: cursor = Curline->s_line + ncol;
510: cursend = &Curline->s_line[CO - 1];
511: i_line = nline;
512: i_col = ncol;
513: }
514:
515: #if !(defined(MAC) || defined(IBMPC))
516: void
517: SO_on()
518: {
519: /* If there are magic cookies, then WHERE the SO string is
520: printed decides where the SO actually starts on the screen.
521: So it's important to make sure the cursor is positioned there
522: anyway. I think this is right. */
523: if (SG != 0) {
524: Placur(i_line, i_col);
525: i_col += SG;
526: CapCol += SG;
527: }
528: putpad(SO, 1);
529: }
530:
531: void
532: SO_off()
533: {
534: /* see comment in SO_on() */
535: if (SG != 0) {
536: Placur(i_line, i_col);
537: i_col += SG;
538: CapCol += SG;
539: }
540: putpad(SE, 1);
541: }
542: #endif
543:
544: /* Insert `num' lines a top, but leave all the lines BELOW `bottom'
545: alone (at least they won't look any different when we are done).
546: This changes the screen array AND does the physical changes. */
547:
548: void
549: v_ins_line(num, top, bottom)
550: int num,
551: top,
552: bottom;
553: {
554: register int i;
555:
556: /* Save the screen pointers. */
557:
558: for(i = 0; i < num && top + i <= bottom; i++)
559: Savelines[i] = Screen[bottom - i];
560:
561: /* Num number of bottom lines will be lost.
562: Copy everything down num number of times. */
563:
564: for (i = bottom; i > top && i-num >= 0; i--)
565: Screen[i] = Screen[i - num];
566:
567: /* Restore the saved ones, making them blank. */
568:
569: for (i = 0; i < num; i++) {
570: Screen[top + i] = Savelines[i];
571: clrline(Screen[top + i].s_line, Screen[top + i].s_length);
572: Screen[top + i].s_length = Screen[top + i].s_line;
573: }
574:
575: #if !(defined(IBMPC) || defined(MAC))
576: (*TTins_line)(top, bottom, num);
577: #endif
578:
579: #ifdef MAC
580: i_lines(top, bottom, num);
581: #endif
582:
583: #ifdef IBMPC
584: scr_win((int) -num, (unsigned char) top, 0, (unsigned char) bottom, CHPL-1);
585: #endif
586: }
587:
588: /* Delete `num' lines starting at `top' leaving the lines below `bottom'
589: alone. This updates the internal image as well as the physical image. */
590:
591: void
592: v_del_line(num, top, bottom)
593: int num,
594: top,
595: bottom;
596: {
597: register int i,
598: bot;
599:
600: bot = bottom;
601:
602: /* Save the lost lines. */
603:
604: for (i = 0; i < num && top + i <= bottom; i++)
605: Savelines[i] = Screen[top + i];
606:
607: /* Copy everything up num number of lines. */
608:
609: for (i = top; num + i <= bottom; i++)
610: Screen[i] = Screen[i + num];
611:
612: /* Restore the lost ones, clearing them. */
613:
614: for (i = 0; i < num; i++) {
615: Screen[bottom - i] = Savelines[i];
616: clrline(Screen[bot].s_line, Screen[bot].s_length);
617: Screen[bot].s_length = Screen[bot].s_line;
618: bot -= 1;
619: }
620:
621: #if !(defined(IBMPC) || defined(MAC))
622: (*TTdel_line)(top, bottom, num);
623: #endif
624:
625: #ifdef MAC
626: d_lines(top, bottom, num);
627: #endif
628:
629: #ifdef IBMPC
630: scr_win(num, (unsigned char) top, 0, (unsigned char) bottom, CHPL-1);
631: #endif
632:
633: }
634:
635: #if !(defined(MAC) || defined(IBMPC)) /* remainder of this file */
636:
637: /* The cursor optimization happens here. You may decide that this
638: is going too far with cursor optimization, or perhaps it should
639: limit the amount of checking to when the output speed is slow.
640: What ever turns you on ... */
641:
642: struct cursaddr {
643: int cm_numchars;
644: void (*cm_proc) ();
645: };
646:
647: private char *Cmstr;
648: private struct cursaddr *HorMin,
649: *VertMin,
650: *DirectMin;
651:
652: private void
653: GENi_lines proto((int, int, int)),
654: GENd_lines proto((int, int, int)),
655: ForMotion proto((int)),
656: ForTab proto((int)),
657: BackMotion proto((int)),
658: RetTab proto((int)),
659: DownMotion proto((int)),
660: UpMotion proto((int)),
661: GoDirect proto((int, int)),
662: HomeGo proto((int, int)),
663: BottomUp proto((int, int));
664:
665:
666: private struct cursaddr WarpHor[] = {
667: 0, ForMotion,
668: 0, ForTab,
669: 0, BackMotion,
670: 0, RetTab
671: };
672:
673: private struct cursaddr WarpVert[] = {
674: 0, DownMotion,
675: 0, UpMotion
676: };
677:
678: private struct cursaddr WarpDirect[] = {
679: 0, GoDirect,
680: 0, HomeGo,
681: 0, BottomUp
682: };
683:
684: #undef FORWARD
685: #define FORWARD 0 /* Move forward */
686: #define FORTAB 1 /* Forward using tabs */
687: #undef BACKWARD
688: #define BACKWARD 2 /* Move backward */
689: #define RETFORWARD 3 /* Beginning of line and then tabs */
690: #define NUMHOR 4
691:
692: #define DOWN 0 /* Move down */
693: #define UPMOVE 1 /* Move up */
694: #define NUMVERT 2
695:
696: #define DIRECT 0 /* Using CM */
697: #define HOME 1 /* HOME */
698: #define LOWER 2 /* Lower Line */
699: #define NUMDIRECT 3
700:
701: #define home() Placur(0, 0)
702: #define LowLine() { putpad(LL, 1); CapLine = ILI; CapCol = 0; }
703: #define PrintHo() { putpad(HO, 1); CapLine = CapCol = 0; }
704:
705: int phystab = 8;
706:
707: private void
708: GoDirect(line, col)
709: register int line,
710: col;
711: {
712: putpad(Cmstr, 1);
713: CapLine = line;
714: CapCol = col;
715: }
716:
717: private void
718: RetTab(col)
719: register int col;
720: {
721: jputchar('\r');
722: CapCol = 0;
723: ForTab(col);
724: }
725:
726: private void
727: HomeGo(line, col)
728: int line,
729: col;
730: {
731: PrintHo();
732: DownMotion(line);
733: ForTab(col);
734: }
735:
736: private void
737: BottomUp(line, col)
738: register int line,
739: col;
740: {
741: LowLine();
742: UpMotion(line);
743: ForTab(col);
744: }
745:
746: /* Tries to move forward using tabs (if possible). It tabs to the
747: closest tabstop which means it may go past 'destcol' and backspace
748: to it. */
749:
750: private void
751: ForTab(destcol)
752: int destcol;
753: {
754: register int tabgoal,
755: ntabs,
756: tabstp = phystab;
757:
758: if (TABS && (tabstp > 0)) {
759: tabgoal = destcol + (tabstp / 2);
760: tabgoal -= (tabgoal % tabstp);
761:
762: /* Don't tab to last place or else it is likely to screw up. */
763: if (tabgoal >= CO)
764: tabgoal -= tabstp;
765:
766: ntabs = (tabgoal / tabstp) - (CapCol / tabstp);
767: while (--ntabs >= 0)
768: jputchar('\t');
769: CapCol = tabgoal;
770: }
771: if (CapCol > destcol)
772: BackMotion(destcol);
773: else if (CapCol < destcol)
774: ForMotion(destcol);
775: }
776:
777: private void
778: ForMotion(destcol)
779: register int destcol;
780: {
781: register int nchars = destcol - CapCol;
782: register char *cp = &Screen[CapLine].s_line[CapCol];
783:
784: while (--nchars >= 0)
785: jputchar(*cp++ & CHARMASK);
786: CapCol = destcol;
787: }
788:
789: private void
790: BackMotion(destcol)
791: register int destcol;
792: {
793: register int nchars = CapCol - destcol;
794:
795: if (BC)
796: while (--nchars >= 0)
797: putpad(BC, 1);
798: else
799: while (--nchars >= 0)
800: jputchar('\b');
801: CapCol = destcol;
802: }
803:
804: private void
805: DownMotion(destline)
806: register int destline;
807: {
808: register int nlines = destline - CapLine;
809:
810: while (--nlines >= 0)
811: putpad(DO, 1);
812: CapLine = destline;
813: }
814:
815: private void
816: UpMotion(destline)
817: register int destline;
818: {
819: register int nchars = CapLine - destline;
820:
821: while (--nchars >= 0)
822: putpad(UP, 1);
823: CapLine = destline;
824: }
825:
826: #ifdef ID_CHAR
827: static int EIlen;
828: #endif
829:
830: #ifndef IBMPC
831:
832: void
833: InitCM()
834: {
835: HOlen = HO ? strlen(HO) : 1000;
836: LLlen = LL ? strlen(LL) : 1000;
837: UPlen = UP ? strlen(UP) : 1000;
838: #ifdef ID_CHAR
839: if (EI)
840: EIlen = strlen(EI);
841: #endif
842: }
843:
844: private int ForNum proto((int from, int to));
845:
846: void
847: Placur(line, col)
848: int line,
849: col;
850: {
851: int dline, /* Number of lines to move */
852: dcol; /* Number of columns to move */
853: register int best,
854: i;
855: register struct cursaddr *cp;
856: int xtracost = 0; /* Misc addition to cost. */
857:
858: #define CursMin(which,addrs,max) { \
859: for (best = 0, cp = &(addrs)[1], i = 1; i < (max); i++, cp++) \
860: if (cp->cm_numchars < (addrs)[best].cm_numchars) \
861: best = i; \
862: (which) = &(addrs)[best]; \
863: }
864:
865: if (line == CapLine && col == CapCol)
866: return; /* We are already there. */
867:
868: dline = line - CapLine;
869: dcol = col - CapCol;
870: #ifdef ID_CHAR
871: if (IN_INSmode && MI)
872: xtracost = EIlen + IMlen;
873: /* If we're already in insert mode, it is likely that we will
874: want to be in insert mode again, after the insert. */
875: #endif
876:
877: /* Number of characters to move horizontally for each case.
878: 1: Just move forward by typing the right character on the screen.
879: 2: Print the correct number of back spaces.
880: 3: Try tabbing to the correct place.
881: 4: Try going to the beginning of the line, and then tab. */
882:
883: if (dcol == 1 || dcol == 0) { /* Most common case. */
884: HorMin = &WarpHor[FORWARD];
885: HorMin->cm_numchars = dcol + xtracost;
886: } else {
887: WarpHor[FORWARD].cm_numchars = dcol >= 0 ? dcol + xtracost : 1000;
888: WarpHor[BACKWARD].cm_numchars = dcol < 0 ? -(dcol + xtracost) : 1000;
889: WarpHor[FORTAB].cm_numchars = dcol >= 0 && TABS ?
890: ForNum(CapCol, col) + xtracost : 1000;
891: WarpHor[RETFORWARD].cm_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col));
892:
893: /* Which is the shortest of the bunch */
894:
895: CursMin(HorMin, WarpHor, NUMHOR);
896: }
897:
898: /* Moving vertically is more simple. */
899:
900: WarpVert[DOWN].cm_numchars = dline >= 0 ? dline : 1000;
901: WarpVert[UPMOVE].cm_numchars = dline < 0 ? ((-dline) * UPlen) : 1000;
902:
903: /* Which of these is simpler */
904: CursMin(VertMin, WarpVert, NUMVERT);
905:
906: /* Homing first and lowering first are considered
907: direct motions.
908: Homing first's total is the sum of the cost of homing
909: and the sum of tabbing (if possible) to the right. */
910:
911: if (VertMin->cm_numchars + HorMin->cm_numchars <= 3) {
912: DirectMin = &WarpDirect[DIRECT]; /* A dummy ... */
913: DirectMin->cm_numchars = 100;
914: } else {
915: WarpDirect[DIRECT].cm_numchars = CM ?
916: strlen(Cmstr = tgoto(CM, col, line)) : 1000;
917: WarpDirect[HOME].cm_numchars = HOlen + line +
918: WarpHor[RETFORWARD].cm_numchars;
919: WarpDirect[LOWER].cm_numchars = LLlen + ((ILI - line) * UPlen) +
920: WarpHor[RETFORWARD].cm_numchars;
921: CursMin(DirectMin, WarpDirect, NUMDIRECT);
922: }
923:
924: if (HorMin->cm_numchars + VertMin->cm_numchars < DirectMin->cm_numchars) {
925: if (line != CapLine)
926: (*VertMin->cm_proc)(line);
927: if (col != CapCol) {
928: #ifdef ID_CHAR
929: if (IN_INSmode) /* We may use real characters ... */
930: INSmode(0);
931: #endif
932: (*HorMin->cm_proc)(col);
933: }
934: } else {
935: #ifdef ID_CHAR
936: if (IN_INSmode && !MI)
937: INSmode(0);
938: #endif
939: (*DirectMin->cm_proc)(line, col);
940: }
941: }
942:
943: #endif /* IBMPC */
944:
945: #define abs(x) ((x) >= 0 ? (x) : -(x))
946:
947: private int
948: ForNum(from, to)
949: register int from;
950: int to;
951: {
952: register int tabgoal,
953: tabstp = phystab;
954: int numchars = 0;
955:
956: if (from >= to)
957: return from - to;
958: if (TABS && (tabstp > 0)) {
959: tabgoal = to + (tabstp / 2);
960: tabgoal -= (tabgoal % tabstp);
961: if (tabgoal >= CO)
962: tabgoal -= tabstp;
963: numchars = (tabgoal / tabstop) - (from / tabstp);
964: from = tabgoal;
965: }
966: return numchars + abs(from - to);
967: }
968:
969: #ifdef WIRED_TERMS
970:
971: private void
972: BGi_lines(top, bottom, num)
973: int top,
974: bottom,
975: num;
976: {
977: writef("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num);
978: CapCol = CapLine = 0;
979: }
980:
981: private void
982: SUNi_lines(top, bottom, num)
983: int top,
984: bottom,
985: num;
986: {
987: Placur(bottom - num + 1, 0);
988: writef("\033[%dM", num);
989: Placur(top, 0);
990: writef("\033[%dL", num);
991: }
992:
993: private void
994: C100i_lines(top, bottom, num)
995: int top,
996: bottom,
997: num;
998: {
999: if (num <= 1) {
1000: GENi_lines(top, bottom, num);
1001: return;
1002: }
1003: writef("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
1004: CapLine = CapCol = 0;
1005: Placur(top, 0);
1006: while (num--)
1007: putpad(AL, ILI - CapLine);
1008: writef("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
1009: CapLine = CapCol = 0;
1010: }
1011:
1012: #endif /* WIRED_TERMS */
1013:
1014: private void
1015: GENi_lines(top, bottom, num)
1016: int top,
1017: bottom,
1018: num;
1019: {
1020: register int i;
1021:
1022: if (CS) {
1023: putpad(tgoto(CS, bottom, top), 1);
1024: CapCol = CapLine = 0;
1025: Placur(top, 0);
1026: for (i = 0; i < num; i++)
1027: putpad(SR, bottom - top);
1028: putpad(tgoto(CS, ILI, 0), 1);
1029: CapCol = CapLine = 0;
1030: } else {
1031: Placur(bottom - num + 1, 0);
1032: if (M_DL && (num > 1)) {
1033: putargpad(M_DL, num, ILI - CapLine);
1034: } else {
1035: for (i = 0; i < num; i++)
1036: putpad(DL, ILI - CapLine);
1037: }
1038: Placur(top, 0);
1039: if (M_AL && (num > 1)) {
1040: putargpad(M_AL, num, ILI - CapLine);
1041: } else {
1042: for (i = 0; i < num; i++)
1043: putpad(AL, ILI - CapLine);
1044: }
1045: }
1046: }
1047:
1048: #ifdef WIRED_TERMS
1049:
1050: private void
1051: BGd_lines(top, bottom, num)
1052: int top,
1053: bottom,
1054: num;
1055: {
1056: writef("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num);
1057: CapCol = CapLine = 0;
1058: }
1059:
1060: private void
1061: SUNd_lines(top, bottom, num)
1062: int top,
1063: bottom,
1064: num;
1065: {
1066: Placur(top, 0);
1067: writef("\033[%dM", num);
1068: Placur(bottom + 1 - num, 0);
1069: writef("\033[%dL", num);
1070: }
1071:
1072: private void
1073: C100d_lines(top, bottom, num)
1074: int top,
1075: bottom,
1076: num;
1077: {
1078: if (num <= 1) {
1079: GENd_lines(top, bottom, num);
1080: return;
1081: }
1082: writef("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
1083: CapLine = CapCol = 0;
1084: Placur(top, 0);
1085: while (num--)
1086: putpad(DL, ILI - CapLine);
1087: writef("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
1088: CapLine = CapCol = 0;
1089: }
1090:
1091: #endif /* WIRED_TERMS */
1092:
1093: private void
1094: GENd_lines(top, bottom, num)
1095: int top,
1096: bottom,
1097: num;
1098: {
1099: register int i;
1100:
1101: if (CS) {
1102: putpad(tgoto(CS, bottom, top), 1);
1103: CapCol = CapLine = 0;
1104: Placur(bottom, 0);
1105: for (i = 0; i < num; i++)
1106: putpad(SF, bottom - top);
1107: putpad(tgoto(CS, ILI, 0), 1);
1108: CapCol = CapLine = 0;
1109: } else {
1110: Placur(top, 0);
1111: if (M_DL && (num > 1)) {
1112: putargpad(M_DL, num, ILI - top);
1113: } else {
1114: for (i = 0; i < num; i++)
1115: putpad(DL, ILI - top);
1116: }
1117: Placur(bottom + 1 - num, 0);
1118: if (M_AL && (num > 1)) {
1119: putargpad(M_AL, num, ILI - CapLine);
1120: } else {
1121: for (i = 0; i < num; i++)
1122: putpad(AL, ILI - CapLine);
1123: }
1124: }
1125: }
1126:
1127: private const struct ID_lookup {
1128: char *ID_name;
1129: void (*I_proc) proto((int, int, int)); /* proc to insert lines */
1130: void (*D_proc) proto((int, int, int)); /* proc to delete lines */
1131: } ID_trms[] = {
1132: "generic", GENi_lines, GENd_lines, /* This should stay here */
1133: #ifdef WIRED_TERMS
1134: "sun", SUNi_lines, SUNd_lines,
1135: "bg", BGi_lines, BGd_lines,
1136: "c1", C100i_lines, C100d_lines,
1137: #endif /* WIRED_TERMS */
1138: 0, 0, 0
1139: };
1140:
1141: void
1142: IDline_setup(tname)
1143: char *tname;
1144: {
1145: register const struct ID_lookup *idp;
1146:
1147: for (idp = &ID_trms[1]; idp->ID_name; idp++)
1148: if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0)
1149: break;
1150: if (idp->ID_name == 0)
1151: idp = &ID_trms[0];
1152: #ifndef IBMPC
1153: TTins_line = idp->I_proc;
1154: TTdel_line = idp->D_proc;
1155: #endif
1156: }
1157:
1158: #endif /* MAC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.