|
|
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 "io.h"
10: #include "ctype.h"
11: #include "termcap.h"
12:
13: #ifdef IBMPC
14:
15: /* here come the actual emulation routines */
16:
17: #include <dos.h>
18: #include <conio.h>
19:
20: #define BYTE unsigned char
21: #define WORD unsigned int
22:
23: #ifdef MAC
24: # undef private
25: # define private
26: #endif
27:
28: #ifdef LINT_ARGS
29: private BYTE near get_mode(void);
30:
31: private WORD
32: near cur_page(void),
33: near get_cur(void);
34:
35: private void
36: near ch_out(BYTE, BYTE),
37: near clr_eop(void),
38: near cur_advance(void),
39: near cur_down(void),
40: near cur_left(void),
41: near cur_right(void),
42: near cur_up(void),
43: near line_feed(void),
44: near normfun(char),
45: near scr_win(int, BYTE, BYTE, BYTE, BYTE),
46: near set_cur(WORD),
47: near set_mode(BYTE),
48: near wherexy(BYTE *, BYTE *);
49: #else
50: private BYTE near get_mode();
51:
52: private WORD
53: near cur_page(),
54: near get_cur();
55:
56: private void
57: near ch_out(),
58: near clr_eop(),
59: near cur_advance(),
60: near cur_down(),
61: near cur_left(),
62: near cur_right(),
63: near cur_up(),
64: near line_feed(),
65: near normfun(),
66: near scr_win(),
67: near set_cur(),
68: near set_mode(),
69: near wherexy();
70: #endif /* LINT_ARGS */
71:
72: #ifdef MAC
73: # undef private
74: # define private static
75: #endif
76:
77: #define VIDEO 0x10
78:
79: #define intr(n, r) int86(n, r, r);
80:
81: BYTE CHPL=80,
82: LPP=25,
83: CUR_PAGE=0,
84: C_ATTR = 0x07,
85: C_X=0,
86: C_Y=0;
87:
88: int Fgcolor = 7,
89: Bgcolor = 0,
90: Mdcolor = 0;
91:
92: void setcolor(fg, bg)
93: BYTE fg, bg;
94: {
95: C_ATTR = ((bg&0xf)<<4)|(fg&0xf);
96: }
97:
98: private
99: WORD near cur_page()
100: {
101: union REGS vr;
102:
103: vr.h.ah = 0x0f;
104: intr(VIDEO, &vr);
105: return(vr.h.bh);
106: }
107:
108: private
109: void near set_cur(xy)
110: WORD xy;
111: {
112: union REGS vr;
113:
114: vr.h.bh = CUR_PAGE;
115: vr.h.ah = 0x02;
116: vr.x.dx = xy;
117: intr(VIDEO, &vr);
118: }
119:
120: private
121: WORD near get_cur()
122: {
123: union REGS vr;
124:
125: vr.h.bh = CUR_PAGE;
126: vr.h.ah = 0x03;
127: intr(VIDEO, &vr);
128: return (vr.x.dx);
129: }
130:
131: private
132: BYTE near get_mode()
133: {
134: union REGS vr;
135:
136: vr.h.ah = 0x0f;
137: intr(VIDEO, &vr);
138: return(vr.h.al);
139: }
140:
141: BYTE lpp()
142: {
143: int far *regen = (int far *) 0x44C;
144: int what;
145: BYTE chpl();
146:
147: what = (*regen&0xff00)/2/chpl();
148: return (what > 43 ? 25 : what);
149: }
150:
151: private
152: void near set_mode(n)
153: BYTE n;
154: {
155: union REGS vr;
156:
157: vr.h.ah = 0x00;
158: vr.h.al = n;
159: intr(VIDEO, &vr);
160: }
161:
162: #define gotoxy(x,y) set_cur((x)<<8|((y)&0xff))
163: #define cur_mov(x,y) set_cur((C_X=x)<<8|((C_Y=y)&0xff))
164:
165: private
166: void near wherexy( x, y)
167: BYTE *x, *y;
168: {
169: register WORD xy;
170:
171: xy = get_cur();
172: *x = xy>>8;
173: *y = xy&0xff;
174: }
175:
176: #define wherex() C_X
177: #define wherey() C_Y
178:
179: private
180: void near scr_win(no, ulr, ulc, lrr, lrc)
181: int no;
182: BYTE ulr, ulc, lrr, lrc;
183: {
184: union REGS vr;
185:
186: if (no >= 0)
187: vr.h.ah = 0x06;
188: else {
189: vr.h.ah = 0x07;
190: no = - no;
191: }
192: vr.h.al = no;
193: vr.x.cx = ulr<<8 | ulc;
194: vr.x.dx = lrr<<8 | lrc;
195: vr.h.bh = C_ATTR;
196: intr(VIDEO, &vr);
197: }
198:
199: BYTE chpl()
200: {
201: union REGS vr;
202:
203: vr.h.ah = 0x0f;
204: intr(VIDEO, &vr);
205: return(vr.h.ah);
206: }
207:
208: #define clr_page() scr_win(0, 0, 0, LPP-1, CHPL-1), \
209: gotoxy(C_X = 0, C_Y = 0)
210:
211: private
212: void near cur_right()
213: {
214: if (C_Y < CHPL-1)
215: C_Y++;
216: gotoxy(C_X, C_Y);
217: }
218:
219: private
220: void near cur_up()
221: {
222: if (C_X)
223: C_X--;
224: gotoxy(C_X, C_Y);
225: }
226:
227: private
228: void near cur_left()
229: {
230: if (C_Y)
231: C_Y--;
232: gotoxy(C_X, C_Y);
233: }
234:
235: private
236: void near cur_down()
237: {
238: if (C_X < LPP-1)
239: C_X++;
240: gotoxy(C_X, C_Y);
241: }
242:
243: private
244: void near ch_out(c, n)
245: BYTE c, n;
246: {
247: union REGS vr;
248:
249: vr.h.ah = 0x09;
250: vr.h.al = c;
251: vr.h.bl = C_ATTR;
252: vr.h.bh = CUR_PAGE;
253: vr.x.cx = n;
254: intr(VIDEO, &vr);
255: }
256:
257: #define wrch(c) ch_out((c), 1), cur_advance()
258:
259: #define home_cur() gotoxy(C_X = 0, C_Y = 0)
260:
261: #define clr_eoln() ch_out(' ', CHPL-wherey())
262:
263: private
264: void near clr_eop()
265: {
266: clr_eoln();
267: scr_win(LPP-1-wherex(), wherex()+1, 0, LPP-1, CHPL-1);
268: }
269:
270: void init_43()
271: {
272: BYTE far *info = (BYTE far *) 0x487;
273: WORD far *CRTC = (WORD far *) 0x463;
274: union REGS vr;
275: WORD cur;
276:
277: CUR_PAGE = cur_page();
278: CHPL = chpl();
279: LPP = lpp();
280:
281: if (get_mode()!=3)
282: set_mode(3);
283: cur = get_cur();
284:
285: vr.x.ax = 0x1112;
286: vr.h.bl = 0;
287: intr(VIDEO, &vr);
288:
289: *info |= 1;
290: vr.x.ax = 0x0100;
291: vr.h.bh = 0;
292: vr.x.cx = 0x0600;
293: intr(VIDEO, &vr);
294:
295: outp(*CRTC, 0x14);
296: outp(*CRTC+1, 0x07);
297:
298: vr.x.ax = 0x1200;
299: vr.h.bl = 0x20;
300: intr(VIDEO, &vr);
301:
302: LPP = lpp();
303:
304: set_cur(cur);
305: wherexy(&C_X, &C_Y);
306: }
307:
308: void reset_43()
309: {
310: BYTE far *info = (BYTE far *) 0x487;
311: WORD far *CRTC = (WORD far *) 0x463;
312: union REGS vr;
313:
314: set_mode(3);
315:
316: *info &= 128;
317: vr.x.ax = 0x0100;
318: vr.h.bh = 0x0607;
319: vr.x.cx = 0x0607;
320: intr(VIDEO, &vr);
321:
322: outp(*CRTC, 0x14);
323: outp(*CRTC+1, 13);
324:
325: }
326:
327: #define scr_up() scr_win(1, 0, 0, LPP-1, CHPL-1)
328: #define back_space() cur_left()
329:
330: private
331: void near line_feed()
332: {
333: if (++C_X > LPP-1) {
334: C_X = LPP-1;
335: scr_up();
336: }
337: gotoxy(C_X, C_Y);
338: }
339:
340: #define BELL_P 0x61 /* speaker */
341: #define BELL_D 0x2dc /* 550 hz */
342: #define TIME_P 0x40 /* timer */
343: #define TINI 182 /* 10110110b timer initialization */
344:
345: void dobell(x)
346: {
347: unsigned int n = 0x8888;
348: int orgval;
349:
350: outp(TIME_P+3, TINI);
351: outp(TIME_P+2, BELL_D&0xff);
352: outp(TIME_P+2, BELL_D>>8);
353: orgval = inp(BELL_P);
354: outp(BELL_P, orgval|3); /* turn speaker on */
355: while (--n > 0)
356: ;
357: outp(BELL_P, orgval);
358: }
359:
360: #define carriage_return() gotoxy(wherex(), C_Y = 0)
361:
362: private
363: void near cur_advance()
364: {
365: if (++C_Y > CHPL-1) {
366: C_Y = 0;
367: if (++C_X > LPP-1) {
368: scr_up();
369: C_X = LPP-1;
370: }
371: }
372: gotoxy(C_X, C_Y);
373: }
374:
375: void init_term()
376: {
377: if (lpp() == 43)
378: reset_43();
379: CUR_PAGE = cur_page();
380: CHPL = chpl();
381: LPP = lpp();
382: wherexy(&C_X, &C_Y);
383: }
384:
385: private
386: void near normfun();
387:
388: void write_em(s)
389: char *s;
390: {
391: while (*s)
392: normfun(*s++);
393: }
394:
395: void write_emif(s)
396: char *s;
397: {
398: if (s)
399: write_em(s);
400: }
401:
402: void write_emc(s, n)
403: char *s;
404: int n;
405: {
406: while (n--)
407: normfun(*s++);
408: }
409:
410: private
411: void near normfun(c)
412: char c;
413: {
414: switch (c) {
415: case 10: line_feed(); break;
416: case 13: carriage_return(); break;
417: case 8: back_space(); break;
418: case 7: dobell(0); break;
419: case 0: break;
420: default: wrch(c);
421: }
422: }
423:
424: #endif /* IBMPC */
425:
426:
427: extern int BufSize;
428:
429: int AbortCnt,
430: tabstop = 8;
431:
432: #if !(defined(IBMPC) || defined(MAC))
433: int (*TTins_line)(),
434: (*TTdel_line)();
435: #endif /* (defined(IBMPC) || defined(MAC)) */
436:
437: struct scrimage
438: *DesiredScreen = 0,
439: *PhysScreen = 0;
440:
441: struct screenline *Screen = 0, /* the screen (a bunch of screenline) */
442: *Savelines = 0, /* another bunch (LI of them) */
443: *Curline = 0; /* current line */
444: char *cursor, /* offset into current Line */
445: *cursend;
446:
447: int CapCol,
448: CapLine,
449:
450: i_line,
451: i_col;
452:
453: void
454: make_scr()
455: {
456: register int i;
457: register struct screenline *ns;
458: register char *nsp;
459:
460: #ifdef RESHAPING
461: /* In case we are RESHAPING the window! */
462: if (DesiredScreen)
463: free((char *) DesiredScreen);
464: if (PhysScreen)
465: free((char *) PhysScreen);
466: if (Savelines)
467: free((char *) Savelines);
468: if (Screen) {
469: free(Screen->s_line); /* free all the screen data */
470: free((char *) Screen);
471: }
472: #endif /* RESHAPING */
473:
474: DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
475: PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
476:
477: Savelines = (struct screenline *)
478: malloc((unsigned) LI * sizeof(struct screenline));
479: ns = Screen = (struct screenline *)
480: malloc((unsigned) LI * sizeof(struct screenline));
481:
482: nsp = (char *) malloc((unsigned)CO * LI);
483: if (nsp == 0) {
484: printf("\n\rCannot malloc screen!\n");
485: finish(1);
486: }
487:
488: for (i = 0; i < LI; i++) {
489: ns->s_line = nsp;
490: nsp += CO;
491: ns->s_length = nsp - 1; /* End of Line */
492: ns += 1;
493: }
494: cl_scr(0);
495: }
496:
497: void
498: clrline(cp1, cp2)
499: register char *cp1,
500: *cp2;
501: {
502: while (cp1 <= cp2)
503: *cp1++ = ' ';
504: }
505:
506: #if !(defined(IBMPC) || defined(MAC))
507: # define sputc(c) ((*cursor != (char) (c)) ? dosputc(c) : (cursor++, i_col++))
508: #endif /* (defined(IBMPC) || defined(MAC)) */
509:
510: #ifdef IBMPC
511: int force = 0;
512: # define sputc(c) dosputc(c)
513: #endif /* IBMPC */
514:
515: #ifdef MAC
516: # define sputc(c) bufputc(c) /* line buffered for mac display */
517: #endif /* MAC */
518:
519: #define soutputc(c) if (--n <= 0) break; else sputc(c)
520:
521: void
522: cl_eol()
523: {
524: if (cursor > cursend)
525: return;
526:
527: if (cursor < Curline->s_length) {
528: #if !(defined(IBMPC) || defined(MAC))
529: if (CE) {
530: #endif /* (defined(IBMPC) || defined(MAC)) */
531: Placur(i_line, i_col);
532: #ifdef TERMCAP
533: putpad(CE, 1);
534: #else
535: clr_eoln();
536: #endif /* TERMCAP */
537: clrline(cursor, Curline->s_length);
538: #if !(defined(IBMPC) || defined(MAC))
539: } else {
540: /* Ugh. The slow way for dumb terminals. */
541: register char *savecp = cursor;
542:
543: while (cursor <= Curline->s_length)
544: sputc(' ');
545: cursor = savecp;
546: }
547: #endif /* (defined(IBMPC) || defined(MAC)) */
548: Curline->s_length = cursor;
549: }
550: }
551:
552: void
553: cl_scr(doit)
554: {
555: register int i;
556: register struct screenline *sp = Screen;
557:
558: for (i = 0; i < LI; i++, sp++) {
559: clrline(sp->s_line, sp->s_length);
560: sp->s_length = sp->s_line;
561: PhysScreen[i].s_id = 0;
562: }
563: if (doit) {
564: #ifdef TERMCAP
565: putpad(CL, LI);
566: #else
567: clr_page();
568: #endif /* TERMCAP */
569: CapCol = CapLine = 0;
570: UpdMesg = YES;
571: }
572: }
573:
574: #ifdef ID_CHAR
575: extern int IN_INSmode;
576: #endif
577:
578: /* Output one character (if necessary) at the current position */
579:
580: #ifndef MAC
581: int /* only for lints sake */
582: dosputc(c)
583: register char c;
584: {
585: #ifndef IBMPC
586: if (*cursor != c) {
587: # ifdef ID_CHAR
588: if (IN_INSmode)
589: INSmode(0);
590: # endif
591: #else /* IBMPC */
592: if ((force) || (*cursor != c)) {
593: #endif /* IBMPC */
594: if (i_line != CapLine || i_col != CapCol)
595: Placur(i_line, i_col);
596: #ifndef IBMPC
597: if (UL && (c & CHARMASK) == '_' && (*cursor & CHARMASK) != ' ')
598: putstr(" \b"); /* Erase so '_' looks right. */
599: #endif /* IBMPC */
600: *cursor++ = c;
601: #ifndef IBMPC
602: putchar(c & CHARMASK);
603: #else /* IBMPC */
604: normfun(c);
605: #endif /* IBMPC */
606: AbortCnt -= 1;
607: CapCol += 1;
608: i_col += 1;
609: } else {
610: cursor += 1;
611: i_col += 1;
612: }
613: }
614: #else /* MAC */
615:
616: /* Character output to bit-mapped screen is very expensive. It makes
617: much more sense to write the entire line at once. So, we print all
618: the characters, whether already there or not, once the line is
619: complete. */
620:
621: #define BUFFLUSH (char) 0
622: #define BUFSTART (char) 1
623:
624: bufputc(c)
625: register char c;
626: {
627: static char buf[256];
628: static int len = 0;
629:
630: if(c == BUFSTART) {
631: /* if (i_line != CapLine || i_col != CapCol)*/
632: NPlacur(i_line, i_col);
633: len = 0;
634: return;
635: }
636: if(c == BUFFLUSH) {
637: buf[0] = (unsigned char) len;
638: writechr(buf);
639: len = 0;
640: }
641: else {
642: if(len > 255) return;
643: *cursor++ = c;
644: if(c == '0') buf[++len] = 0xAF; /* slashed zero */
645: else buf[++len] = c;
646: CapCol++;
647: i_col++;
648: }
649: return;
650: }
651: #endif /* MAC */
652:
653: /* Write `line' at the current position of `cursor'. Stop when we
654: reach the end of the screen. Aborts if there is a character
655: waiting. */
656:
657: #ifdef MAC /* This was getting too complicated with ifdefs ... */
658: int
659: swrite(line, inversep, abortable)
660: register char *line;
661: register int abortable;
662: {
663: register int c;
664: int col = i_col,
665: aborted = 0;
666: register int n = cursend - cursor;
667:
668: if (n <= 0)
669: return 1;
670: sputc(BUFSTART); /* Okay, because no interruption possible */
671:
672: while (c = *line++) {
673: if (c == '\t') {
674: int nchars;
675:
676: nchars = (tabstop - (col % tabstop));
677: col += nchars;
678:
679: while (nchars--)
680: soutputc(' ');
681: if (n <= 0)
682: break;
683: } else if (isctrl(c)) {
684: soutputc('^');
685: c = ((c == '\177') ? '?' : c + '@');
686: soutputc(c);
687: col += 2;
688: } else {
689: soutputc(c);
690: col += 1;
691: }
692: }
693: if (n <= 0) {
694: if ((*line == '\0') && (c != '\t') && !isctrl(c))
695: sputc(c);
696: sputc('!');
697: }
698: if (cursor > Curline->s_length)
699: Curline->s_length = cursor;
700: sputc(BUFFLUSH);
701: return !aborted;
702: }
703: #else /* MAC */
704:
705: int
706: swrite(line, inversep, abortable)
707: register char *line;
708: register int abortable;
709: {
710: register int c;
711: int col = i_col,
712: aborted = 0;
713: register int n = cursend - cursor;
714: #ifndef IBMPC
715: int or_byte = inversep ? 0200 : 0,
716: thebyte;
717: #else
718: int thebyte;
719: #endif /* IBMPC */
720:
721: #ifdef IBMPC
722: force = inversep? 1: 0; /* to force a redraw of the modeline */
723: #endif /* IBMPC */
724:
725: if (n <= 0)
726: return 1;
727: while (c = *line++) {
728: #if !(defined(IBMPC) || defined(MAC)) /* don't check after every character */
729: if (abortable && AbortCnt < 0) {
730: AbortCnt = BufSize;
731: if (InputPending = charp()) {
732: aborted = 1;
733: break;
734: }
735: }
736: #endif /* (defined(IBMPC) || defined(MAC)) */
737: if (c == '\t') {
738: int nchars;
739:
740: nchars = (tabstop - (col % tabstop));
741: col += nchars;
742:
743: #ifndef IBMPC
744: thebyte = (' ' | or_byte);
745: #endif /* IBMPC */
746: while (nchars--)
747: #ifndef IBMPC
748: soutputc(thebyte);
749: #else /* IBMPC */
750: soutputc(' ');
751: #endif /* IBMPC */
752: if (n <= 0)
753: break;
754: } else if (isctrl(c)) {
755: #ifndef IBMPC
756: thebyte = ('^' | or_byte);
757: soutputc(thebyte);
758: thebyte = (((c == '\177') ? '?' : c + '@') | or_byte);
759: soutputc(thebyte);
760: #else /* IBMPC */
761: soutputc('^');
762: c = ((c == '\177') ? '?' : c + '@');
763: soutputc(c);
764: #endif /* IBMPC */
765: col += 2;
766: } else {
767: #ifndef IBMPC
768: thebyte = (c | or_byte);
769: soutputc(thebyte);
770: #else /* IBMPC */
771: if (c == 255) c = 1;
772: if (c == ' ' && inversep) c = 255;
773: soutputc(c);
774: #endif /* IBMPC */
775: col += 1;
776: }
777: }
778: if (n <= 0) {
779: if ((*line == '\0') && (c != '\t') && !isctrl(c))
780: #ifndef IBMPC
781: sputc(c|or_byte);
782: #else /* IBMPC */
783: sputc(c);
784: #endif /* IBMPC */
785: else
786: #ifndef IBMPC
787: sputc('!'|or_byte);
788: #else /* IBMPC */
789: sputc('!');
790: #endif /* IBMPC */
791: }
792: if (cursor > Curline->s_length)
793: Curline->s_length = cursor;
794: #ifdef IBMPC
795: force = 0;
796: #endif
797: return !aborted;
798: }
799: #endif /* MAC */
800: /* This is for writing a buffer line to the screen. This is to
801: minimize the amount of copying from one buffer to another buffer.
802: This gets the info directly from the disk buffers. */
803:
804: int
805: BufSwrite(linenum)
806: {
807: register int n = cursend - cursor,
808: col = 0,
809: c = -1;
810: register char *bp;
811: int StartCol = DesiredScreen[linenum].s_offset,
812: visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE,
813: aborted = 0;
814:
815: bp = lcontents(DesiredScreen[linenum].s_lp);
816: if (*bp) for (;;) {
817: if (col >= StartCol) {
818: DesiredScreen[linenum].s_offset = col;
819: break;
820: }
821:
822: c = *bp++ & CHARMASK;
823: if (c == '\0')
824: break;
825: if (c == '\t')
826: col += (tabstop - (col % tabstop));
827: else if (isctrl(c))
828: col += 2;
829: else
830: col += 1;
831: }
832: #ifdef MAC
833: sputc(BUFSTART); /* Okay because we can't be interrupted */
834: #endif
835:
836: if (c != '\0') while (c = *bp++) {
837: #if !(defined(IBMPC) || defined(MAC)) /* will never get true so why bother */
838: if (AbortCnt < 0) {
839: AbortCnt = BufSize;
840: if (InputPending = charp()) {
841: aborted = 1;
842: break;
843: }
844: }
845: #endif /* (defined(IBMPC) || defined(MAC)) */
846: if (c == '\t') {
847: int nchars = (tabstop - (col % tabstop));
848:
849: col += nchars;
850: if (visspace) {
851: soutputc('>');
852: nchars -= 1;
853: }
854: while (--nchars >= 0)
855: soutputc(' ');
856: if (n <= 0)
857: break;
858: } else if (isctrl(c)) {
859: soutputc('^');
860: soutputc((c == '\177') ? '?' : c + '@');
861: col += 2;
862: } else {
863: if (c == ' ' && visspace)
864: c = '_';
865: #ifdef IBMPC
866: if (c == 255)
867: c = 1;
868: #endif /* IBMPC */
869: soutputc(c);
870: col += 1;
871: }
872: }
873: if (n <= 0) {
874: if ((*bp == '\0') && (c != '\t') && !isctrl(c))
875: sputc(c);
876: else
877: sputc('!');
878: }
879: if (cursor > Curline->s_length)
880: Curline->s_length = cursor;
881: #ifdef MAC
882: sputc(BUFFLUSH);
883: #endif
884: return !aborted; /* Didn't abort */
885: }
886:
887: void
888: i_set(nline, ncol)
889: register int nline,
890: ncol;
891: {
892: Curline = &Screen[nline];
893: cursor = Curline->s_line + ncol;
894: cursend = &Curline->s_line[CO - 1];
895: i_line = nline;
896: i_col = ncol;
897: }
898:
899: /* Insert `num' lines a top, but leave all the lines BELOW `bottom'
900: alone (at least they won't look any different when we are done).
901: This changes the screen array AND does the physical changes. */
902:
903: void
904: v_ins_line(num, top, bottom)
905: {
906: register int i;
907:
908: /* Save the screen pointers. */
909:
910: for(i = 0; i < num && top + i <= bottom; i++)
911: Savelines[i] = Screen[bottom - i];
912:
913: /* Num number of bottom lines will be lost.
914: Copy everything down num number of times. */
915:
916: for (i = bottom; i > top && i-num >= 0; i--)
917: Screen[i] = Screen[i - num];
918:
919: /* Restore the saved ones, making them blank. */
920:
921: for (i = 0; i < num; i++) {
922: Screen[top + i] = Savelines[i];
923: clrline(Screen[top + i].s_line, Screen[top + i].s_length);
924: Screen[top + i].s_length = Screen[top + i].s_line;
925: }
926:
927: #if !(defined(IBMPC) || defined(MAC))
928: (*TTins_line)(top, bottom, num);
929: #endif
930:
931: #ifdef MAC
932: i_lines(top, bottom, num);
933: #endif
934:
935: #ifdef IBMPC
936: scr_win(-num, top, 0, bottom, CHPL-1);
937: #endif
938: }
939:
940: /* Delete `num' lines starting at `top' leaving the lines below `bottom'
941: alone. This updates the internal image as well as the physical image. */
942:
943: void
944: v_del_line(num, top, bottom)
945: {
946: register int i,
947: bot;
948:
949: bot = bottom;
950:
951: /* Save the lost lines. */
952:
953: for (i = 0; i < num && top + i <= bottom; i++)
954: Savelines[i] = Screen[top + i];
955:
956: /* Copy everything up num number of lines. */
957:
958: for (i = top; num + i <= bottom; i++)
959: Screen[i] = Screen[i + num];
960:
961: /* Restore the lost ones, clearing them. */
962:
963: for (i = 0; i < num; i++) {
964: Screen[bottom - i] = Savelines[i];
965: clrline(Screen[bot].s_line, Screen[bot].s_length);
966: Screen[bot].s_length = Screen[bot].s_line;
967: bot -= 1;
968: }
969:
970: #if !(defined(IBMPC) || defined(MAC))
971: (*TTdel_line)(top, bottom, num);
972: #endif
973:
974: #ifdef MAC
975: d_lines(top, bottom, num);
976: #endif
977:
978: #ifdef IBMPC
979: scr_win(num, top, 0, bottom, CHPL-1);
980: #endif
981:
982: }
983:
984: #ifndef MAC /* remainder of this file */
985: #ifdef IBMPC
986:
987: /* No cursor optimization on an IBMPC, this simplifies things a lot.
988: Think about it: it would be silly!
989: */
990:
991: int phystab = 8;
992:
993: void
994: Placur(line, col)
995: {
996: cur_mov(line, col);
997: CapCol = col;
998: CapLine = line;
999: }
1000:
1001: void
1002: SO_on()
1003: {
1004: if (Mdcolor)
1005: setcolor(Mdcolor&0xf, Mdcolor>>4);
1006: else
1007: setcolor(Bgcolor, Fgcolor);
1008: }
1009:
1010: void
1011: SO_off()
1012: {
1013: setcolor(Fgcolor, Bgcolor);
1014: }
1015:
1016: extern int EGA;
1017:
1018: void
1019:
1020: UnsetTerm(foo)
1021: char *foo;
1022: {
1023: Placur(ILI, 0);
1024: clr_eoln();
1025: if (EGA)
1026: reset_43();
1027: }
1028:
1029:
1030: void
1031: ResetTerm()
1032: {
1033: if (EGA)
1034: init_43();
1035: else
1036: init_term();
1037:
1038: do_sgtty(); /* this is so if you change baudrate or stuff
1039: like that, JOVE will notice. */
1040: ttyset(ON);
1041: }
1042:
1043: #else /* IBMPC */
1044:
1045: /* The cursor optimization happens here. You may decide that this
1046: is going too far with cursor optimization, or perhaps it should
1047: limit the amount of checking to when the output speed is slow.
1048: What ever turns you on ... */
1049:
1050: private struct cursaddr {
1051: int cm_numchars,
1052: (*cm_proc)();
1053: };
1054:
1055: private char *Cmstr;
1056: private struct cursaddr *HorMin,
1057: *VertMin,
1058: *DirectMin;
1059:
1060: private void
1061: GENi_lines(),
1062: GENd_lines(),
1063: ForMotion(),
1064: ForTab(),
1065: BackMotion(),
1066: RetTab(),
1067: DownMotion(),
1068: UpMotion(),
1069: GoDirect(),
1070: HomeGo(),
1071: BottomUp();
1072:
1073:
1074: private struct cursaddr WarpHor[] = {
1075: 0, ForMotion,
1076: 0, ForTab,
1077: 0, BackMotion,
1078: 0, RetTab
1079: };
1080:
1081: private struct cursaddr WarpVert[] = {
1082: 0, DownMotion,
1083: 0, UpMotion
1084: };
1085:
1086: private struct cursaddr WarpDirect[] = {
1087: 0, GoDirect,
1088: 0, HomeGo,
1089: 0, BottomUp
1090: };
1091:
1092: #undef FORWARD
1093: #define FORWARD 0 /* Move forward */
1094: #define FORTAB 1 /* Forward using tabs */
1095: #undef BACKWARD
1096: #define BACKWARD 2 /* Move backward */
1097: #define RETFORWARD 3 /* Beginning of line and then tabs */
1098: #define NUMHOR 4
1099:
1100: #define DOWN 0 /* Move down */
1101: #define UPMOVE 1 /* Move up */
1102: #define NUMVERT 2
1103:
1104: #define DIRECT 0 /* Using CM */
1105: #define HOME 1 /* HOME */
1106: #define LOWER 2 /* Lower Line */
1107: #define NUMDIRECT 3
1108:
1109: #define home() Placur(0, 0)
1110: #define LowLine() putpad(LL, 1), CapLine = ILI, CapCol = 0
1111: #define PrintHo() putpad(HO, 1), CapLine = CapCol = 0
1112:
1113: int phystab = 8;
1114:
1115: private void
1116: GoDirect(line, col)
1117: register int line,
1118: col;
1119: {
1120: putpad(Cmstr, 1);
1121: CapLine = line;
1122: CapCol = col;
1123: }
1124:
1125: private void
1126: RetTab(col)
1127: register int col;
1128: {
1129: putchar('\r');
1130: CapCol = 0;
1131: ForTab(col);
1132: }
1133:
1134: private void
1135: HomeGo(line, col)
1136: {
1137: PrintHo();
1138: DownMotion(line);
1139: ForTab(col);
1140: }
1141:
1142: private void
1143: BottomUp(line, col)
1144: register int line,
1145: col;
1146: {
1147: LowLine();
1148: UpMotion(line);
1149: ForTab(col);
1150: }
1151:
1152: /* Tries to move forward using tabs (if possible). It tabs to the
1153: closest tabstop which means it may go past 'destcol' and backspace
1154: to it. */
1155:
1156: private void
1157: ForTab(destcol)
1158: int destcol;
1159: {
1160: register int tabgoal,
1161: ntabs,
1162: tabstp = phystab;
1163:
1164: if (TABS && (tabstp > 0)) {
1165: tabgoal = destcol + (tabstp / 2);
1166: tabgoal -= (tabgoal % tabstp);
1167:
1168: /* Don't tab to last place or else it is likely to screw up. */
1169: if (tabgoal >= CO)
1170: tabgoal -= tabstp;
1171:
1172: ntabs = (tabgoal / tabstp) - (CapCol / tabstp);
1173: while (--ntabs >= 0)
1174: putchar('\t');
1175: CapCol = tabgoal;
1176: }
1177: if (CapCol > destcol)
1178: BackMotion(destcol);
1179: else if (CapCol < destcol)
1180: ForMotion(destcol);
1181: }
1182:
1183: private void
1184: ForMotion(destcol)
1185: register int destcol;
1186: {
1187: register int nchars = destcol - CapCol;
1188: register char *cp = &Screen[CapLine].s_line[CapCol];
1189:
1190: while (--nchars >= 0)
1191: putchar(*cp++ & CHARMASK);
1192: CapCol = destcol;
1193: }
1194:
1195: private void
1196: BackMotion(destcol)
1197: register int destcol;
1198: {
1199: register int nchars = CapCol - destcol;
1200:
1201: if (BC)
1202: while (--nchars >= 0)
1203: putpad(BC, 1);
1204: else
1205: while (--nchars >= 0)
1206: putchar('\b');
1207: CapCol = destcol;
1208: }
1209:
1210: private void
1211: DownMotion(destline)
1212: register int destline;
1213: {
1214: register int nlines = destline - CapLine;
1215:
1216: while (--nlines >= 0)
1217: putpad(NL, 1);
1218: CapLine = destline;
1219: }
1220:
1221: private void
1222: UpMotion(destline)
1223: register int destline;
1224: {
1225: register int nchars = CapLine - destline;
1226:
1227: while (--nchars >= 0)
1228: putpad(UP, 1);
1229: CapLine = destline;
1230: }
1231:
1232: #ifdef ID_CHAR
1233: static int EIlen;
1234: #endif
1235: extern int IMlen;
1236:
1237: void
1238: InitCM()
1239: {
1240: HOlen = HO ? strlen(HO) : 1000;
1241: LLlen = LL ? strlen(LL) : 1000;
1242: UPlen = UP ? strlen(UP) : 1000;
1243: #ifdef ID_CHAR
1244: if (EI)
1245: EIlen = strlen(EI);
1246: #endif
1247: }
1248:
1249: void
1250: Placur(line, col)
1251: {
1252: int dline, /* Number of lines to move */
1253: dcol; /* Number of columns to move */
1254: register int best,
1255: i;
1256: register struct cursaddr *cp;
1257: int xtracost = 0; /* Misc addition to cost. */
1258:
1259: #define CursMin(which,addrs,max) \
1260: for (best = 0, cp = &addrs[1], i = 1; i < max; i++, cp++) \
1261: if (cp->cm_numchars < addrs[best].cm_numchars) \
1262: best = i; \
1263: which = &addrs[best];
1264:
1265: if (line == CapLine && col == CapCol)
1266: return; /* We are already there. */
1267:
1268: dline = line - CapLine;
1269: dcol = col - CapCol;
1270: #ifdef ID_CHAR
1271: if (IN_INSmode && MI)
1272: xtracost = EIlen + IMlen;
1273: /* If we're already in insert mode, it is likely that we will
1274: want to be in insert mode again, after the insert. */
1275: #endif
1276:
1277: /* Number of characters to move horizontally for each case.
1278: 1: Just move forward by typing the right character on the screen.
1279: 2: Print the correct number of back spaces.
1280: 3: Try tabbing to the correct place.
1281: 4: Try going to the beginning of the line, and then tab. */
1282:
1283: if (dcol == 1 || dcol == 0) { /* Most common case. */
1284: HorMin = &WarpHor[FORWARD];
1285: HorMin->cm_numchars = dcol + xtracost;
1286: } else {
1287: WarpHor[FORWARD].cm_numchars = dcol >= 0 ? dcol + xtracost : 1000;
1288: WarpHor[BACKWARD].cm_numchars = dcol < 0 ? -(dcol + xtracost) : 1000;
1289: WarpHor[FORTAB].cm_numchars = dcol >= 0 && TABS ?
1290: ForNum(CapCol, col) + xtracost : 1000;
1291: WarpHor[RETFORWARD].cm_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col));
1292:
1293: /* Which is the shortest of the bunch */
1294:
1295: CursMin(HorMin, WarpHor, NUMHOR);
1296: }
1297:
1298: /* Moving vertically is more simple. */
1299:
1300: WarpVert[DOWN].cm_numchars = dline >= 0 ? dline : 1000;
1301: WarpVert[UPMOVE].cm_numchars = dline < 0 ? ((-dline) * UPlen) : 1000;
1302:
1303: /* Which of these is simpler */
1304: CursMin(VertMin, WarpVert, NUMVERT);
1305:
1306: /* Homing first and lowering first are considered
1307: direct motions.
1308: Homing first's total is the sum of the cost of homing
1309: and the sum of tabbing (if possible) to the right. */
1310:
1311: if (VertMin->cm_numchars + HorMin->cm_numchars <= 3) {
1312: DirectMin = &WarpDirect[DIRECT]; /* A dummy ... */
1313: DirectMin->cm_numchars = 100;
1314: } else {
1315: WarpDirect[DIRECT].cm_numchars = CM ?
1316: strlen(Cmstr = tgoto(CM, col, line)) : 1000;
1317: WarpDirect[HOME].cm_numchars = HOlen + line +
1318: WarpHor[RETFORWARD].cm_numchars;
1319: WarpDirect[LOWER].cm_numchars = LLlen + ((ILI - line) * UPlen) +
1320: WarpHor[RETFORWARD].cm_numchars;
1321: CursMin(DirectMin, WarpDirect, NUMDIRECT);
1322: }
1323:
1324: if (HorMin->cm_numchars + VertMin->cm_numchars < DirectMin->cm_numchars) {
1325: if (line != CapLine)
1326: (*VertMin->cm_proc)(line);
1327: if (col != CapCol) {
1328: #ifdef ID_CHAR
1329: if (IN_INSmode) /* We may use real characters ... */
1330: INSmode(0);
1331: #endif
1332: (*HorMin->cm_proc)(col);
1333: }
1334: } else {
1335: #ifdef ID_CHAR
1336: if (IN_INSmode && !MI)
1337: INSmode(0);
1338: #endif
1339: (*DirectMin->cm_proc)(line, col);
1340: }
1341: }
1342:
1343: #define abs(x) ((x) >= 0 ? (x) : -(x))
1344:
1345: int
1346: ForNum(from, to)
1347: register int from;
1348: {
1349: register int tabgoal,
1350: tabstp = phystab;
1351: int numchars = 0;
1352:
1353: if (from >= to)
1354: return from - to;
1355: if (TABS && (tabstp > 0)) {
1356: tabgoal = to + (tabstp / 2);
1357: tabgoal -= (tabgoal % tabstp);
1358: if (tabgoal >= CO)
1359: tabgoal -= tabstp;
1360: numchars = (tabgoal / tabstop) - (from / tabstp);
1361: from = tabgoal;
1362: }
1363: return numchars + abs(from - to);
1364: }
1365:
1366: #ifdef WIRED_TERMS
1367:
1368: void
1369: BGi_lines(top, bottom, num)
1370: {
1371: printf("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num);
1372: CapCol = CapLine = 0;
1373: }
1374:
1375: void
1376: SUNi_lines(top, bottom, num)
1377: {
1378: Placur(bottom - num + 1, 0);
1379: printf("\033[%dM", num);
1380: Placur(top, 0);
1381: printf("\033[%dL", num);
1382: }
1383:
1384: void
1385: C100i_lines(top, bottom, num)
1386: {
1387: if (num <= 1) {
1388: GENi_lines(top, bottom, num);
1389: return;
1390: }
1391: printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
1392: CapLine = CapCol = 0;
1393: Placur(top, 0);
1394: while (num--)
1395: putpad(AL, ILI - CapLine);
1396: printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
1397: CapLine = CapCol = 0;
1398: }
1399:
1400: #endif /* WIRED_TERMS */
1401:
1402: private void
1403: GENi_lines(top, bottom, num)
1404: {
1405: register int i;
1406:
1407: if (CS) {
1408: putpad(tgoto(CS, bottom, top), 1);
1409: CapCol = CapLine = 0;
1410: Placur(top, 0);
1411: for (i = 0; i < num; i++)
1412: putpad(SR, bottom - top);
1413: putpad(tgoto(CS, ILI, 0), 1);
1414: CapCol = CapLine = 0;
1415: } else {
1416: Placur(bottom - num + 1, 0);
1417: if (M_DL && (num > 1)) {
1418: char minibuf[16];
1419:
1420: sprintf(minibuf, M_DL, num);
1421: putpad(minibuf, ILI - CapLine);
1422: } else {
1423: for (i = 0; i < num; i++)
1424: putpad(DL, ILI - CapLine);
1425: }
1426: Placur(top, 0);
1427: if (M_AL && (num > 1)) {
1428: char minibuf[16];
1429:
1430: sprintf(minibuf, M_AL, num);
1431: putpad(minibuf, ILI - CapLine);
1432: } else {
1433: for (i = 0; i < num; i++)
1434: putpad(AL, ILI - CapLine);
1435: }
1436: }
1437: }
1438:
1439: #ifdef WIRED_TERMS
1440:
1441: void
1442: BGd_lines(top, bottom, num)
1443: {
1444: printf("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num);
1445: CapCol = CapLine = 0;
1446: }
1447:
1448: void
1449: SUNd_lines(top, bottom, num)
1450: {
1451: Placur(top, 0);
1452: printf("\033[%dM", num);
1453: Placur(bottom + 1 - num, 0);
1454: printf("\033[%dL", num);
1455: }
1456:
1457: void
1458: C100d_lines(top, bottom, num)
1459: {
1460: if (num <= 1) {
1461: GENd_lines(top, bottom, num);
1462: return;
1463: }
1464: printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
1465: CapLine = CapCol = 0;
1466: Placur(top, 0);
1467: while (num--)
1468: putpad(DL, ILI - CapLine);
1469: printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
1470: CapLine = CapCol = 0;
1471: }
1472:
1473: #endif /* WIRED_TERMS */
1474:
1475: private void
1476: GENd_lines(top, bottom, num)
1477: {
1478: register int i;
1479:
1480: if (CS) {
1481: putpad(tgoto(CS, bottom, top), 1);
1482: CapCol = CapLine = 0;
1483: Placur(bottom, 0);
1484: for (i = 0; i < num; i++)
1485: putpad(SF, bottom - top);
1486: putpad(tgoto(CS, ILI, 0), 1);
1487: CapCol = CapLine = 0;
1488: } else {
1489: Placur(top, 0);
1490: if (M_DL && (num > 1)) {
1491: char minibuf[16];
1492:
1493: sprintf(minibuf, M_DL, num);
1494: putpad(minibuf, ILI - top);
1495: } else {
1496: for (i = 0; i < num; i++)
1497: putpad(DL, ILI - top);
1498: }
1499: Placur(bottom + 1 - num, 0);
1500: if (M_AL && (num > 1)) {
1501: char minibuf[16];
1502:
1503: sprintf(minibuf, M_AL, num);
1504: putpad(minibuf, ILI - CapLine);
1505: } else {
1506: for (i = 0; i < num; i++)
1507: putpad(AL, ILI - CapLine);
1508: }
1509: }
1510: }
1511:
1512: struct ID_lookup {
1513: char *ID_name;
1514: int (*I_proc)(); /* proc to insert lines */
1515: int (*D_proc)(); /* proc to delete lines */
1516: } ID_trms[] = {
1517: "generic", GENi_lines, GENd_lines, /* This should stay here */
1518: #ifdef WIRED_TERMS
1519: "sun", SUNi_lines, SUNd_lines,
1520: "bg", BGi_lines, BGd_lines,
1521: "c1", C100i_lines, C100d_lines,
1522: #endif /* WIRED_TERMS */
1523: 0, 0, 0
1524: };
1525:
1526: void
1527: IDline_setup(tname)
1528: char *tname;
1529: {
1530: register struct ID_lookup *idp;
1531:
1532: for (idp = &ID_trms[1]; idp->ID_name; idp++)
1533: if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0)
1534: break;
1535: if (idp->ID_name == 0)
1536: idp = &ID_trms[0];
1537: TTins_line = idp->I_proc;
1538: TTdel_line = idp->D_proc;
1539: }
1540:
1541: #endif /* IBMPC */
1542: #endif /* MAC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.