|
|
1.1 root 1: /* EMACS_MODES: c !fill */
2:
3: #include "emacs_io.h"
4: #include "emacs_gb.h"
5: #include "emacs_disp.h"
6: #ifdef TERMINFO
7: #include <sys/types.h>
8: #include <sys/termio.h>
9: #define SGTTY struct termio
10: #include <term.h>
11: #endif
12:
13: /* character insert */
14:
15: /* inserts count occurances of the character c in the file */
16:
17:
18:
19: insertc(count,c)
20:
21: register char c;
22: register int count;
23:
24: {
25:
26: if (count < 0) return; /* Reject bad count */
27: while (count--) {
28: if ((OVERW) && (c != EOL) && (clptr[column] != EOL)) {
29:
30: clptr[column] = c;
31: sputl(curln,column,curln); /* fix this line */
32: modify(curln);
33: column++;
34: } else {
35: if(put(c)==0) break;
36: }
37: }
38: }
39:
40: /* insert one character into the file at current position */
41:
42: put(c)
43:
44: register char c;
45: /* Keywords: commands:10 insertion line-representation:50 */
46: {
47:
48: register char tc;
49: register int xcol;
50:
51: if (c == EOL) {
52: nl(1);
53: return(1);
54: }
55: xcol=column;
56: while (c!= EOL) {
57: tc = clptr[xcol];
58: clptr[xcol++] = c;
59: c = tc;
60: }
61: modify(curln);
62: clptr = ckline(curln,xcol);
63: if (clptr == NULL) {
64: clptr = mkline(curln);
65: *(clptr+xcol-1) = EOL;
66: return(0);
67: }
68: clptr[xcol] = EOL;
69: sputl(curln,column,curln); /* fix this line */
70: move(curln,column+1);
71: return(1);
72: }
73:
74: /* tabc -- tab command */
75: /* inserts a tab unless notabs mode is on, in which case */
76: /* it inserts spaces up to next tabstop. */
77:
78: tabc(count,arg)
79:
80: register int count;
81: int arg;
82:
83: /* Keywords: commands insertion */
84: {
85: if (infrn >= 0) { /* no dice in macro */
86: if (NOTABS) {
87: while (count--) {
88: do {
89: put(' ');
90: } while (column%TABSTOP);
91: }
92: } else {
93: insertc(count,arg);
94: }
95: }
96: return(1);
97: }
98:
99: /* mvc -- move with checking for c<=length(l) */
100:
101:
102:
103: mvc(l,c)
104: register int l;
105: register int c;
106:
107: /* Keywords: commands:40 movement */
108: {
109: register int x;
110:
111: if ((x = leng(l)) < c) move(l,x);
112: else move (l,c);
113: }
114: /* move to new position in the file */
115:
116: move (newln,newcol)
117: register int newln;
118: register int newcol;
119:
120: {
121: /* Keywords: movement buffer-allocation:20 */
122:
123: if (newln < 1) newln = 1;
124: if (newln >= NPTRS) {
125: if (!growbuf(newln)) {
126: newln = NPTRS-1;
127: }
128: }
129: curln = newln;
130: clptr = mkline(curln);
131: column = newcol;
132: return;
133: }
134:
135: /* move both the display matrix pointer and the actual display to the
136: * specified line and column */
137:
138: mgo(x,y)
139:
140: register int x,y;
141:
142: {
143:
144: sgo(mline = x,mcol = y);
145: }
146:
147:
148: /* move the display cursor to the specified destination. sgo attempts
149: * to optimize the movement, using single character or absolute
150: * positioning */
151: #ifdef PC
152: sgo(x,y)
153: register int x,y;
154: {
155:
156: video(REG(POS_CUR,0),REG(PAGE_0,0),0,REG(x,y));
157:
158: }
159: #else
160: sgo(x,y)
161: /* Keywords: screen-handling the-screen-cursor */
162: register int x,y;
163:
164: {
165: int mx,my;
166: int xcost; /* cost with all relative movement */
167: int ycost; /* cost with carriage return */
168: /* acost is cost of absolute positioning */
169:
170: /* calculate relative costs of various movements. cost functions */
171: /* automatically indicate that un-doable motions have infinite cost */
172:
173:
174: if (umode) unline(); /* out of "underline mode" */
175:
176: /* calculate xcost and ycost */
177:
178: mx = x-scrlin;
179: if (mx<0) {
180: mx = -mx;
181: xcost = mx*lUP;
182: } else xcost = mx*lDOWN;
183:
184: ycost = y + xcost + lCR;
185:
186: my = y-scrcol;
187: if (my<0) {
188: my = -my;
189: xcost +=my*lBAK;
190: } else xcost += my;
191:
192: if (xcost == 0) return; /* Catch spurious calls to sgo */
193:
194: if (acost < ycost) {
195: if (acost < xcost) {
196: /* do absolute positioning */
197: if (CURAD) {
198: absmove(x,y);
199: } else { /* have relative addrs */
200: if (x>scrlin) eprintf (RELDOWN,mx);
201: if (x<scrlin) eprintf (RELUP,mx);
202: if (y>scrcol) eprintf (RELFORW,my);
203: if (y<scrcol) eprintf (RELBACK,my);
204: }
205: scrlin=x;
206: scrcol=y;
207: return;
208: } /* else relative is cheap, do it */
209: } else {
210: if (osert && (MI == 0)) {
211: unsert(); /* LEAVE insert character mode */
212: }
213: if (ycost < xcost) {
214: /* do carriage return processing */
215: PUTS(CR); /* carriage return */
216: scrcol = 0;
217:
218: /* fall through to finish with relative motion */
219: }
220: }
221:
222: while (x != scrlin) {
223: if (x < scrlin) {
224: PUTS(UP);
225: scrlin--;
226: } else {
227: PUTS(DOWN);
228: scrlin++;
229: }
230: }
231:
232: /* now correct row */
233:
234: while (y != scrcol) {
235: if (y < scrcol) {
236: PUTS(BACK);
237: scrcol--;
238: } else {
239: if ((FORWARD == NULL)|| (FORWARD[1] && (osert==0))) {
240: if (osert) {
241: unsert();
242: }
243: x = cmap[scrlin] [scrcol];
244: if (x == 0) x=cmap[scrlin] [scrcol] = ' ';
245: if (x & 0200) pu(x); /* underlined character */
246: else {
247: if (umode) unline();
248: putchar(x); /* re-write to move; */
249: }
250: } else {
251: PUTS(FORWARD);
252: }
253: scrcol++;
254: }
255: };
256: return;
257: }
258:
259: /* unsert -- LEAVE insert character mode */
260:
261: unsert()
262: {
263: /* Keywords: screen-handling terminal-parameters insertion character-at-a-time */
264: PUTS(OSERTC); /* can't stay inserting */
265: osert = 0;
266: }
267:
268: unline()
269: {
270: /* Keywords: screen-handling terminal-parameters underlining */
271: PUTS(UEND);
272: umode = 0;
273: }
274:
275: /* vshift -- shift the display image from top to bottom (inclusive) by x */
276:
277:
278: vshift(top,bottom,x)
279: /* Keywords: scrolling the-screen-map terminal-parameters:20 display-update:80 */
280: int top;
281: int bottom;
282: int x;
283:
284: {
285: register int i;
286: register int j;
287: char *cp1;
288: char *cp2;
289: int *jnkptr;
290: int *mapptr;
291: int start;
292: int stop;
293: register int off;
294:
295: if (x > 0) {
296: off = 1;
297: start = top;
298: stop = bottom+1;
299: } else {
300: off = -1;
301: start = bottom;
302: stop = top-1;
303: }
304: for (i = start,mapptr = scrmap+i,jnkptr = scrjnk+i; i != stop-x; i+=off,mapptr+=off,jnkptr+=off) {
305: *jnkptr = *(jnkptr+x);
306: *mapptr = *(mapptr+x);
307: cp1 = cmap[i];
308: cp2 = cmap[i+x];
309: for (j = 0; j < *jnkptr; j++) {
310: *cp1++ = *cp2++;
311: }
312: }
313: while (i != stop) {
314: if (off > 0) {
315: *mapptr++ = *jnkptr++ = 0;
316: i++;
317: } else {
318: *mapptr-- = *jnkptr-- = 0;
319: i--;
320: }
321: }
322: }
323:
324: /* adjust vertical position of line -- open (or close) lines on */
325: /* the screen argument is the number of lines to add (or drop). */
326:
327: vadjust(x,xline)
328:
329: register int x;
330: int xline;
331: /* Keywords: display-update:90 deletion:50 insertion:50 terminal-parameters:90 the-screen-map scrolling:20 screen-lines screen-handling */
332: {
333: register int i;
334: register int j;
335: int oldx;
336:
337:
338: oldx = xline;
339: TRACE(VADJUST);
340: TRACE(curln);
341: TRACE(x);
342: if (x<0) {
343: x = -x;
344: i = 1;
345: } else i = 0;
346: if (((j = lastln-xline-x) <= 0)||
347: ((x*VCOST)>(j*ttywarp*CFILL))) return; /* nothing to save */
348: SREGION=SCRLINES-oldx; /* effected region */
349: if (i) { /* if deleting lines */
350: sgo(xline,0);
351:
352: if (SCREG && CURAD) { /*if vt100 stype scrolling */
353: PUTS(TPARM(SCREG,oldx+XBASE,SCRLINES+XBASE-1)); /*define region*/
354: absmove(0,0);
355: sgo(SCRLINES-1,0);
356: do_n(CLSCROLL,SSCROLL,x); /* Scroll up x lines */
357: PUTS(TPARM(SCREG,XBASE,REALBOT+XBASE-1));
358: absmove(oldx,0);
359: } else {
360: do_n(CLDEL,LDEL,x);
361: sgo(SCRLINES-x,0);
362: do_n(CLOPEN,LOPEN,x);
363: }
364: sgo(oldx,0);
365: vshift (oldx,SCRLINES-1,x);
366: } else {
367: if (SCREG && CURAD && RSCROLL) { /* if vt100 style scrolling */
368:
369: PUTS(TPARM(SCREG,oldx+XBASE,SCRLINES+XBASE-1)); /*define region */
370: absmove(xline,0);
371: do_n(CRSCROLL,RSCROLL,x);
372: PUTS(TPARM(SCREG,XBASE,REALBOT+XBASE-1));
373: absmove(oldx,0);
374: } else {
375: sgo(SCRLINES-x,0);
376: do_n(CLDEL,LDEL,x);
377: sgo(oldx,0);
378: do_n(CLOPEN,LOPEN,x);
379: }
380: mgo(oldx,0);
381:
382: vshift(oldx,SCRLINES-1,-x);
383: }
384: SREGION=1;
385: }
386:
387: do_n(mulcap,sincap,n)
388: char *mulcap;
389: register char *sincap;
390: register int n;
391:
392: /* Keywords: scrolling:20 screen-lines:40 terminal-parameters argument-processing screen-handling */
393:
394: {
395: if (mulcap && (n>1)) {
396: /* If we can do all at once */
397: #ifdef TERMINFO
398: putpad(tparm(mulcap,n));
399: #else
400: PUTS(mulcap,n);
401: #endif
402: } else {
403: while (n--) PUTS(sincap);
404: }
405: }
406:
407: absmove(x, y)
408: int x;
409: int y;
410: {
411: /* Keywords: terminal-parameters the-screen-cursor screen-handling */
412:
413: #ifdef TERMINFO
414: putpad(tparm(CURAD, x, y));
415: #else
416: #ifdef TERMCAP
417: putpad(tgoto(CURAD, y, x));
418: #else
419: if (SRCADD) {
420: eprintf(CURAD,x+XBASE,y+YBASE);
421: } else {
422: eprintf(CURAD,y+YBASE,x+XBASE);
423: }
424: #endif
425: #endif
426: scrlin=x;
427: scrcol=y;
428: }
429:
430: /* sscroll -- try to fix display by scrolling */
431:
432: sscroll(x)
433:
434: register int x;
435: /* Keywords: terminal-parameters scrolling screen-handling */
436: {
437: register int i;
438:
439:
440: if (SSCROLL == NULL || twowind || (SCRLINES-x < 3) || (curbf != disbuf[cwind])) return;
441:
442:
443: sgo(REALBOT-1,0); /* to bottom */
444: SREGION=REALBOT; /* number of lines effected */
445: do_n(CLSCROLL,SSCROLL,x);
446: SREGION=1;
447: vshift (0,SCRNLIN-1,x);
448: if (timemd) disptime = 1; /* Wiped out time display */
449: }
450:
451: #endif PC
452:
453: /* delete chars -- delete characters starting at . */
454:
455: /* all characters must be on the same line */
456:
457: delc(count)
458:
459: register int count;
460:
461: /* Keywords: deletion line-representation killstack:50 stacking:50 commands:20 */
462:
463: {
464: register char *cp1;
465: register char *cp2;
466:
467: undel();
468: killstk(curln,column,curln,column+count); /* stack even on 0 */
469: if (count == 0) {
470: beep();
471: return(0); /* nothing to modify */
472: }
473: cp1 = clptr+column;
474: cp2 = cp1+count;
475: if (NODEL) {
476: while (cp1<cp2) *cp1++=' ';
477: } else {
478: while ((*cp1++ = *cp2++) != EOL);
479: }
480: sputl(curln,column,curln);
481: modify(curln);
482: move(curln,column);
483: return(1);
484: }
485:
486: /* open up count blank lines in the file */
487:
488: openl(count)
489:
490: register int count;
491:
492:
493: /* Keywords: insertion line-representation memory-allocation:30 text-lines the-screen-map:20 screen-lines:50 */
494:
495: {
496:
497: register int i;
498: register char *lp;
499: char *lp1;
500: char *lp2;
501: int oldcol;
502: int oldln;
503:
504: /* first fix the file */
505:
506: if (nlines+count >= NPTRS) {
507: if (!growbuf(nlines+count)) {
508: return;
509: }
510: }
511: if (curln<nlines) {
512: for (i = fbkno; i < NBLOCK; i++) {
513: if (hipt[i]>curln) hipt[i]+=count;
514: if (lowpt[i]>curln) lowpt[i]+=count;
515: }
516: for (i = nlines; i > curln; i--) {
517: ptrs[i+count] = ptrs[i];
518: }
519: }
520: nlines += count;
521: for (i = curln+1; i <= curln+count; i++) ptrs[i] = 0;
522: if (clptr[column] != EOL) {
523: if(ckline(curln+count,leng(curln)-column)!=NULL) {
524: holdin(curln,curln+count);
525: lp1 = mkline(curln+count);
526: lp2 = lp = mkline(curln) + column;
527: while ((*lp1++ = *lp++)!= EOL);
528: *lp2 = EOL;
529: }
530: }
531: modify(curln);
532: modify(curln+count);
533:
534: /* now fix the display */
535:
536: oldln = curln;
537: oldcol = column;
538: if (TABMD && (RARE == 0)) {
539: tabjust(curln+count);
540: }
541: if (disbuf[cwind] == curbf) {
542:
543: /* Adjust scrmap to reflect the change. All lines past oldln in the
544: * current buffer that show on the screen are bumped up by count. The
545: * current line is bumped only if the whole line moved */
546:
547: for (i = wbase; i < SCRLINES; i++) {
548: if ((scrmap[i]) && ((nln = scrmap[i]&SCRMSK) >= oldln)) {
549: if ((nln != oldln) || (oldcol == 0)) scrmap[i] += count;
550: }
551: }
552: }
553: sputl(oldln,oldcol,REST);
554: move(oldln,oldcol);
555: }
556:
557:
558: /* getname prompts for a string, using ps, and inputs a string */
559:
560: /* rubout and @ can be used to edit the string as enterred, and causes
561: * a quit, returning no input string
562: * ^Y causes the current buffer name to be brought out
563: */
564:
565: char *
566: getname(ps)
567:
568: register char *ps;
569:
570: /* Keywords: user-interface prompting key-bindings:50 reading:50 filenames:50 commands:20 text-lines:40 the-screen-cursor:30 macro-hooks:10 */
571:
572: {
573: register int i;
574: register char c;
575: int cnt = 1;
576: char *xp;
577:
578: if (infrn < 0) { /* if in macro */
579: if(retrvs(fnbuf,FNLEN)>=0){
580: return(fnbuf);
581: } else return(NULL);
582: }
583: if (hooks[Read_Name_Hook]) {
584: stkstr(ps);
585: if (hook(Read_Name_Hook) && (retrvs(fnbuf,FNLEN) >= 0)) {
586: return(fnbuf);
587: }else return(NULL);
588: }
589: fnbuf[i=0] = 0;
590: for (;;) {
591: if (infrn == 0 ){
592: prompt(ECHOL,"%s%s",ps,fnbuf); /* display prompt */
593: if (c=fnbuf[i]) { /* If there is stuff past the cursor */
594:
595: /* UGH, To find out where the cursor goes, we must duplicate a lot */
596: /* of ugly code out of prompt! */
597:
598: char pbuf[256];
599: mline = ECHOL;
600: mcol = 0;
601: fnbuf[i]=0;
602: seprintf(pbuf,"%s%s",ps,fnbuf);
603: fnbuf[i]=c;
604: xputl(pbuf,0);
605: }
606: mgo(mline,mcol);
607: }
608: cnt = 1;
609: getbak: donttime=1; /* Avoid time & mail */
610: c = getchar();
611: donttime=0; /* Restore time display */
612: switch(map_it[c]) {
613:
614: case CQUOTE:
615: c = getchar();
616: goto regchar;
617:
618: case CCTLU:
619: cnt*=4;
620: goto getbak; /* Bypass re-initilizing cnt! */
621:
622: case CEQUIT:
623: case CEXIT:
624: beep();
625: unprompt();
626: return(NULL);
627: case CCTLX:
628: xp = mkline(curln);
629: goto wrdin;
630: case CYANK:
631: xp = fname();
632: wrdin: while ((*xp!= 0) && (*xp != EOL)&& (i<FNLEN-1)) {
633: cram(fnbuf,i++,*xp++);
634: }
635: continue;
636: default:
637:
638:
639: /* anything that isn't otherwise mapped comes here. Most just insert, */
640: /* but we do check for '@' */
641:
642: if (c == '@') {
643: fnbuf[0]=0;
644: i = 0;
645: continue;
646: }
647:
648: if (c>=' ') {
649: regchar: if (i<FNLEN-1) cram(fnbuf,i++,c);
650: continue;
651: } else {
652: if ((c != CTRLJ) && (c != CTRLM)) {
653: beep;
654: continue;
655: }
656: }
657:
658: /* Fall through to handle newlines re-mapped by the user */
659:
660: case CNEWLINE:
661: case CMETA:
662: unprompt();
663: if (infrn == 0) mflush(stdout); /* Indicate that we got it */
664: return(fnbuf);
665: case CREFRESH:
666: clear();
667: continue;
668: case CBDEL:
669: while (cnt--) {
670: if (i) {
671: i--;
672: mstrcpy(fnbuf+i,fnbuf+i+1);
673: } else beep();
674: }
675: continue;
676: case CFDEL:
677: while (cnt--) {
678: if (fnbuf[i]) {
679: mstrcpy(fnbuf+i,fnbuf+i+1);
680: } else beep();
681: }
682: continue;
683: case CXPOSE:
684: if (fnbuf[i] && fnbuf[i+1]) {
685: c = fnbuf[i];
686: fnbuf[i]=fnbuf[i+1];
687: fnbuf[++i] = c;
688: }
689: break;
690: case CFORW:
691: while (cnt--) {
692: if (fnbuf[i]) {
693: i++;
694: } else beep();
695: }
696: continue;
697: case CBEGIN:
698: i = 0;
699: continue;
700: case CENDL:
701: i = lng(fnbuf);
702: continue;
703: case CBACK:
704: i-=cnt;
705: if (i<0) {
706: beep();
707: i=0;
708: }
709: continue;
710: case CEKILL:
711: fnbuf[i]=0;
712: continue;
713: }
714: }
715: }
716:
717: /* Cram character into the middle of a filename string */
718:
719: cram(sp,pos,cchar)
720: register char *sp;
721: register int pos,cchar;
722: /* Keywords: user-interface prompting string-handling:40 */
723:
724: {
725:
726: int nc;
727:
728: while (cchar) {
729: if (pos == FNLEN-1) {
730: beep();
731: break;
732: }
733: nc = sp[pos];
734: sp[pos]=cchar;
735: pos++;
736: cchar=nc;
737: }
738: sp[pos]=0;
739: }
740:
741: /* gechar: get EMACS character: */
742: /* returns 0200+c for meta chars, 0400+c for ^X chars */
743:
744:
745: gechar(ps)
746: register char *ps;
747: /* Keywords: user-interface character-at-a-time prompting:40 ^-and-M-processing:70 */
748: {
749: register int c;
750:
751: prompt1("%s: ",ps);
752: c = getchar();
753: if (map_it[c] == CMETA) {
754: prompt1("%s: M-",ps);
755: c = 0200+getchar();
756: }
757: if (map_it[c] == CCTLX) {
758: prompt1("%s: ^X",ps);
759: c = 0400+getchar();
760: }
761: unprompt();
762: return(c);
763: }
764: /* putout outputs a string (like eprintf) at the current position */
765:
766: /* position is advanced by one line. If the position overflows the screen
767: * -MORE- is printed, and input is read. Any character except ^G
768: * continues the display, ^G quits by returning -1 */
769:
770: /*VARARGS1*/
771:
772: putout(string,arg1)
773: char *string;
774: /* Keywords: prompting:10 informational-displays MORE-processing */
775: {
776: if (mline>=SCRLINES) {
777: prompt1("-- MORE --");
778: if ((infrn == 0) && ((getchar()) == CTRLG)) return(-1);
779: unprompt();
780: mline=0; /* TOP */
781: }
782: prompt2(mline,string,&arg1);
783: clrl();
784: mgo(++mline,0);
785: return(0);
786: }
787:
788: /* put out a string on ECHOL */
789: /*VARARGS1*/
790:
791: prompt1(string,arg1)
792: char *string;
793: /* Keywords: prompting */
794:
795: {
796: if (infrn) return; /* prompt only if input from stdin */
797: prompt2(ECHOL,string,&arg1);
798: if (mcol) sgo(mline,mcol); /* Move cursor only if something is there! */
799: }
800:
801: /* Keywords: informational-displays time-processing:50 mail-processing:50 */
802:
803: prompt3(string,arg1)
804: char *string;
805: {
806: if (infrn) return;
807: prompt2(ECHOL-1,string,&arg1);
808: scrmap[ECHOL-1] = ECHOHACK; /* Flag for next unprompt */
809: }
810: /* put out a string at a specified line */
811:
812: /*VARARGS2*/
813:
814: prompt(ecl,string,arg1)
815: int ecl;
816: char *string;
817: int arg1;
818: /* Keywords: informational-displays mode-line user-interface:20 */
819: {
820: prompt2(ecl,string,&arg1);
821: }
822:
823: /* Internal subroutine for all prompting */
824:
825: prompt2(ecl,string,argl)
826: char *string;
827: register int ecl;
828: unsigned int *argl;
829:
830: /* Keywords: prompting informational-displays the-screen-map:40 */
831:
832: {
833: char pbuf[256];
834:
835: mline = ecl;
836: scrmap[mline] = 0; /* wipe out previous display */
837: mcol = 0;
838: sxprintf(pbuf,string,argl);
839: xputl(pbuf,0);
840: psx = mline;
841: psy = mcol;
842: clrl();
843:
844: }
845:
846: /* clear out prompt */
847:
848: unprompt()
849: /* Keywords: prompting informational-displays the-screen-map:40 deletion:10 */
850: {
851: if (infrn) return; /* unprompt only if input from termial */
852: mline = ECHOL;
853: mcol = 0;
854: clrl();
855: if (scrmap[ECHOL-1] == ECHOHACK) {
856: mline = ECHOL-1;
857: clrl();
858: }
859: if (timemd) disptime = 1; /* put time back */
860: }
861:
862: /* multi-line deleter */
863:
864: /* deletes the text between current position, and kline, kcol */
865: /* all deleted text is stacked */
866:
867: tkill()
868: /* Keywords: deletion picture-mode:50 killstack:50 stacking:50 the-screen-map:60 */
869: /* arguments are kline,kcol */
870: {
871: int oldcol;
872: register int x;
873: register int y;
874: register char *cp;
875: char *cp1;
876:
877: if (kline < 1) kline = 1;
878: if (kline >nlines) {
879: kline = nlines;
880: kcol = leng(kline);
881: }
882: if ((kline < curln) || ((kline == curln) && (kcol < column))) {
883: x = curln;
884: y = column;
885: move (kline, kcol);
886: kcol = y;
887: kline = x;
888: }
889:
890:
891: if (kline == curln) {
892: return(delc (kcol-column)); /* cheap out */
893: }
894: oldcol = column;
895: undel();
896: killstk(curln,column,kline,kcol);
897: if (PICMODE) {
898: int mincol;
899: int maxcol;
900: int ln;
901: register int c;
902:
903: ln = curln;
904: if (kcol<column) {
905: mincol=kcol;
906: maxcol=column;
907: } else {
908: mincol=column;
909: maxcol=kcol;
910: }
911: while (ln<=kline) {
912: cp = mkline(ln);
913: c = 0;
914: if (NODEL) {
915: while (c<maxcol) {
916: if (cp[c]==EOL) break;
917: if (c>=mincol) cp[c] = ' ';
918: c++;
919: }
920: } else {
921: int lln;
922:
923: lln = leng(ln);
924: if (lln > mincol) {
925: if (lln < maxcol) {
926: cp[mincol]=EOL;
927: } else {
928: c = mincol;
929: while (1) {
930: cp[c]=(*(cp+c+maxcol-mincol));
931: if (*(cp+(c++))==EOL) break;
932: }
933: }
934: }
935: }
936: modify(ln);
937: ln++;
938: }
939: sputl(curln,column,REST);
940: mvc(curln,column);
941: return(1);
942: }
943: if(ckline(curln,column+leng(kline)-kcol) == NULL) return(0);
944: holdin(curln,kline);
945: cp1 = mkline(curln)+column;
946: cp = mkline(kline)+kcol;
947: while ((*cp1++ = *cp++)!= EOL) column++;
948: modify(curln);
949:
950: /* current line is fixed, fix rest */
951:
952: x = kline-curln;
953:
954: /* Adjust block ranges to account for movement in lines. high point
955: * shifts if its above the deleted region. Low point shifts if it's
956: * in or above */
957:
958: if (curln+x<nlines) {
959: for (y = fbkno; y < NBLOCK; y++) {
960: if (hipt[y]>curln+x) hipt[y]-=x;
961: if (lowpt[y]>curln) lowpt[y]-=x;
962: }
963: }
964:
965: for (y = curln+1+x; y <= nlines; y++) {
966: ptrs[y-x] = ptrs[y];
967: }
968: nlines -= x;
969:
970: if (disbuf[cwind] == curbf) {
971:
972: /* Adjust scrmap to reflect the change. All lines past oldln in the
973: * current buffer that show on the screen are bumped up by count. The
974: * current line is bumped only if the whole line moved */
975:
976: for (y = wbase; y < SCRLINES; y++) {
977: if ((scrmap[y]) && ((nln = scrmap[y]&SCRMSK) >= curln)) {
978: if ((nln == curln) && oldcol) continue; /* dont wipe out curln */
979: if (nln >= (curln+x)) scrmap[y]-=x; /* map down for lines past the deletion */
980: else scrmap[y] = 0; /* this line has been killed */
981: }
982: }
983: }
984:
985: sputl(curln,oldcol,REST);
986: move(curln,oldcol);
987: return(1);
988: }
989:
990: /* refresh the screen */
991:
992: /* clear and force refresh */
993:
994: refresh(arg)
995:
996: register unsigned arg;
997: /* Keywords: display-update commands the-screen-cursor:40 windows:20 */
998: {
999:
1000:
1001: if (numarg) dspage(curln-arg,0);
1002: else clear();
1003: }
1004:
1005: /* mark a region of the displayy for fixing. Arguments are the */
1006: /* first line and (file) character position to fix, and the last line */
1007:
1008: sputl(from, col, to)
1009:
1010: int col;
1011: register int from;
1012: int to;
1013: {
1014: /* Keywords: screen-handling:60 commands:30 display-update:30 deletion:50 insertion:50 */
1015: register int *fmp;
1016: int wwid;
1017:
1018: if (disbuf[cwind] != curbf) return; /* not in this window */
1019: from -= minln;
1020: wwid = SCRLINES-wbase;
1021: fmp = fmap;
1022: to -= minln;
1023: if (to > wwid) to = wwid;
1024: if ((from >= 0) && (from <= wwid)) {
1025: if (fmp[from] > col) fmp[from]= col;
1026: }
1027: while (++from<=to) if (from >= 0) fmp[from]=0;
1028: return;
1029: }
1030:
1031: /* Display output routines. This is probably less clean than the
1032: * previous version, but handles underlining and also does a better
1033: * job with insert/delete character. */
1034:
1035: /* The functions are:
1036:
1037: cflush(buf,n) -- put n-mcol characters starting at buf+mcol on the
1038: screen at current mline,mcol. This is
1039: assumed not to overflow one line.
1040:
1041: xputl(line,flag,col) -- The hard work. Maps a string to one
1042: or more screen lines. The exact nature of
1043: the mapping is different for buffer lines
1044: than for strings, as indicated by flag.
1045: */
1046:
1047:
1048: /* Cflush is the main vehicle for the escape of characters. All
1049: * charcters that actaually print (as opposed to terminal
1050: * control) go through here. The general strategy is that if the
1051: * desired character is by some odd chance there already, nothing
1052: * happens. If the desired character is a space and the terminal is
1053: * beyond the end of the line, nothing happens. If insert or delete
1054: * characters will help bring cp into line with what's on the
1055: * screen, then it will use them as necessary. Underlining is
1056: * handled, including the pain of making it work on various
1057: * brain-damaged terminals. */
1058:
1059: /* These general principals followed in a way that is optimized for
1060: * common cases, including: display of a whole line that is already
1061: * on the screen. Display of a whole line that does not correspond
1062: * to what's on the screen, and display of one new character. */
1063:
1064:
1065: #ifdef PC
1066: #define EOM 0 /* End of string marker */
1067: #else
1068: #define EOM '\337' /* End of line marker */
1069: #endif PC
1070:
1071: cflush(cp,n)
1072:
1073: register char *cp;
1074: int n;
1075:
1076: /* Keywords: character-at-a-time:40 insertion:30 deletion:30 character-output screen-handling terminal-parameters:20 */
1077: {
1078: register char *mp;
1079: register int x;
1080: register int y;
1081: int z;
1082: int jnk;
1083: int stop;
1084:
1085: cp[n] = EOM; /* Mark end of line */
1086:
1087:
1088: #ifdef PC
1089: mcol += vout(mline,mcol,cp+mcol);
1090: if (scrjnk[mline]< mcol) scrjnk[mline]=mcol;
1091: #else
1092: mp = cmap[mline]; /* character map pointer */
1093: x = jnk = scrjnk[mline];
1094: while (x < n) mp[x++] = BLANK; /* Clear out the spaces we will write */
1095: x = mcol; /* Get mcol into a register */
1096: stop = 0;
1097: while (1) {
1098: while (mp[x]== cp[x]) x++; /* skip rapidly over same stuff */
1099: if ((mp[x] == 0) && (cp[x] == ' ')) {
1100: x++;
1101: continue;
1102: }
1103: if ((cp[x] == EOM)) {
1104: mcol = x;
1105: if (x < jnk) x = jnk;
1106: scrjnk[mline] = x;
1107:
1108: if ((scrcol > REALWID) && SCRWRAP) {
1109: scrlin++;
1110: scrcol=0;
1111: }
1112: return;
1113: }
1114:
1115: /* Character was not there, we must do some work here! */
1116:
1117: nmput++; /* count for stats */
1118: if ((x != scrcol) || (mline != scrlin)) sgo(mline,x);
1119:
1120: /* First, see if we have enough left to worry about insert/delete */
1121:
1122: if (jnk-x >= lDELC) {
1123: if (stop == 0) {
1124:
1125: /* Find the last matching position */
1126:
1127: stop = n-1;
1128: if (stop >= jnk) stop = jnk;
1129: while ((mp[stop] == 0) && (cp[stop] == ' ')) stop--;
1130: while (mp[stop] == cp[stop]) stop--;
1131: stop++;
1132: }
1133:
1134: /* Try to use DELC. Must have at least lDELC characters match within
1135: * DLOOK characters of the current position. */
1136:
1137: /* Note: If there are ANY nulls in the characters to be deleted, we */
1138: /* Can't use DELC, since the concept-style terminals won't delete*/
1139:
1140:
1141: if (DELC&& mp[x]) {
1142:
1143: y = 1;
1144: while (y < DLOOK && mp[x+y]) {
1145: if (mp[x+y] == cp[x] ) {
1146: z = dccost * y;
1147: if (y+z+x >stop) goto NoDEL;
1148: if (strncmp(cp+x,mp+x+y,z)) goto NoDEL;
1149: /* Should be next_del, but this is faster */
1150:
1151: /* Delete y characters from under the cursor */
1152:
1153: SREGION=SCRWID-x; /* number of char's gobbled */
1154: if ((DELMODE==1) && (osert == 0)) {
1155: PUTS(INSERTM); /* enter "delete mode, UGH!!!" */
1156: osert = 1;
1157: }
1158: if ((DELMODE==2) && osert) {
1159: unsert(); /* Must not be in insert mode */
1160: }
1161: if (x > jnk) jnk = x;
1162: while (y--) {
1163:
1164: PUTS(DELC); /*clobber next char */
1165: jnk = lshift(scrlin,x,jnk-1);
1166: }
1167: stop = 0; /* Don't know where to stop any more */
1168: SREGION=1;
1169: x += z; /* This many matched */
1170: goto donec; /* Process next character */
1171: }
1172: next_del: y++;
1173: }
1174: }
1175:
1176:
1177: /* Now see if insertion will help. It will be used if lINSC
1178: * characters can be matched within ILOOK characters of the cursor. */
1179:
1180: NoDEL:
1181: if ((INSERTC || INSERTM) && (stop > x+lINSC) && ((cp[x] & 0200) == 0)) {
1182: y = 1;
1183: while ((y<ILOOK) && (x+y < stop) && ((cp[x+y]&0200) == 0)) {
1184: if (cp[x+y] == mp[x]) {
1185:
1186: /* Found a match, now figure out how much we should have to see before inserting */
1187:
1188: if (INSERTC) z = y * iccost;
1189: /* If inserting is per-character, then each one costs iccost */
1190: /* Otherwise, it costs iccost to go into and out of icmode */
1191:
1192: else {
1193: if (osert) z = 0;
1194: else z = iccost;
1195: }
1196: /* After a successful insert, we will need cursor motion, so add that too. */
1197: z += acost;
1198: if ((x+y+z)>stop) goto NOINS;
1199: if (strncmp(cp+x+y,mp+x,z)) goto NOINS;
1200:
1201:
1202:
1203: /* Now insert y characters at point, taking from cp and putting out to
1204: * screen. Note that underscores and overstrikes are rejected
1205: * above, so that nothing here will overstrike. We just blast out
1206: * the characters. */
1207: if (x > jnk) jnk = x;
1208: SREGION=jnk-x; /* number of char's moved */
1209: if (umode) unline();
1210: if ((osert == 0) && INSERTM) {
1211: PUTS(INSERTM); /* insert mode */
1212: osert++;
1213: }
1214:
1215: while (y--) {
1216: if (INSERTC) PUTS(INSERTC); /* insert prepare */
1217: putchar(cp[x]);
1218: if (INSERTP) PUTS(INSERTP); /* insert pad */
1219: jnk = rshift(scrlin,scrcol+1,mp[scrcol]);
1220: mp[scrcol++] = cp[x++];
1221: }
1222: x+= z;
1223: SREGION=1;
1224: stop = 0; /* Stop is no good any more */
1225: goto donec; /* process next character */
1226: }
1227: next_ins: y++;
1228: }
1229: }
1230: }
1231: NOINS: if (osert) {
1232: unsert();
1233: }
1234:
1235: /* Underscore processing. relevant variables are EOVER and ULINE.
1236: * EOVER should be one if writing over an underlined position clears
1237: * it, otherwise, make it zero, and we will clear the line to get
1238: * rid of unwanted underscores. ULINE is a string parameter that
1239: * contains whatever is needed to print the character with an
1240: * underline. If the terminal underscores naturally, then ULINE is
1241: * %c<BS>_. If the terminal has an underscore character mode,
1242: * then ULINE is underscore mode on, %c, underscore mode off. If
1243: * the terminal has an underscore single character command, then
1244: * ULINE is underscore character %c. This is inefficient in
1245: * underscoring giant blocks of text, but this should be rare */
1246:
1247:
1248: if (cp[x]&0200){
1249: pu(cp[x]); /* underlined character */
1250: } else {
1251: if (umode) unline();
1252: if ((mp[x]&0200)&& (!EOVER)) { /* If re-writing won't erase */
1253: PUTS(CLINE); /* wipe line */
1254: while (jnk > scrcol) mp[--jnk] = BLANK; /* Wipeout array */
1255: }
1256: putchar(cp[x]);
1257: }
1258: mp[scrcol++] = cp[x++];
1259: donec: continue;
1260: }
1261: }
1262:
1263: /* print an underscored character. */
1264:
1265:
1266: pu(c)
1267: register char c;
1268: {
1269: /* Keywords: screen-handling:20 underlining character-output:40 */
1270:
1271: register int oc;
1272: if (osert) unsert();
1273: c &= 0177;
1274: if ((c == 0)|| (c == 040)) {
1275: /* bare underscore */
1276: oc = cmap[mline][mcol]&0137; /* Map space to null */
1277: if (EOVER && (UEND || (oc == 0))) {
1278: if (umode) unline();
1279: putchar ('_');
1280: return; /* just put out the underscore */
1281: }
1282: c = ' '; /* make sure that we blank over whats there */
1283: }
1284: if (UEND == 0) {
1285: eprintf(ULINE,c);
1286: } else {
1287: if (umode == 0) eprintf(ULINE); /* enter "underscore mode" */
1288: putchar(c);
1289: umode = 1;
1290: }
1291: }
1292:
1293:
1294:
1295: /* lshift -- left shift the screen to account for delete character */
1296:
1297: lshift (line,col,limit)
1298: int line;
1299: register int col;
1300: register int limit;
1301:
1302: /* Keywords: character-output the-screen-map deletion */
1303: {
1304: register char *lp;
1305: int x;
1306:
1307: lp = cmap[line];
1308: while (col < limit) {
1309: if ((lp[col]=lp[col+1]) == 0) break;
1310: col++;
1311: }
1312: lp[col] = 0;
1313: if (IN && (col == SCRWID)) {
1314: x = lp[col] = cmap[++line] [0];
1315: limit++;
1316: if (x) scrjnk[line] = lshift(line,0,scrjnk[line]-1);
1317: }
1318: return(limit);
1319: }
1320:
1321: /* rshift -- right shift the screen to account for insert character */
1322:
1323: rshift (line,col,x)
1324: int line; /* effected line */
1325: int col; /* column to start in */
1326: register int x; /* displaced character that goes in col */
1327: {
1328: /* Keywords: character-output the-screen-map insertion */
1329:
1330: int y;
1331: int jnk;
1332: register char *stop;
1333: register char *lp;
1334:
1335: lp = cmap[line];
1336: jnk = scrjnk[line];
1337: if (jnk <=SCRWID) lp[jnk] = 0;
1338:
1339: stop = lp+SCRWID;
1340: lp += col;
1341:
1342: while (x && (lp<= stop)) {
1343: y = *lp;
1344: *lp++ = x;
1345: x = y;
1346: }
1347: if (IN) {
1348: y = lp - cmap[line];
1349: if (y > jnk) jnk = y;
1350: if (x) rshift(line+1,0,x);
1351: } else {
1352: if (jnk < SCRWID) jnk++;
1353: }
1354: scrjnk[line] = jnk;
1355: return(jnk);
1356: #endif
1357: }
1358:
1359: /* put a "logical line" of characters on the screen at the current position */
1360:
1361: /* NOTE: This is not very clean, but seems necessary to handle all of the
1362: * various strange possibilities for displaying characters. We must
1363: * process a line at a time in order to handle things like
1364: * underscoring, by which multiple characters map to a single
1365: * display position. The general principals here are: that there
1366: * two ways of calling it, one with a C string to be printed, and
1367: * one with a buffer string to be printed. C strings end in nulls,
1368: * and cause a special character to be mapped to embedded newlines.
1369: * Buffer strings end in newlines, and map normally. Underscoring
1370: * is inidicated by the presence of the meta (0200) bit on
1371: * characters in the display map, so that mapping is done here. To
1372: * do this, a whole line is buffered for cput. Underscoring will
1373: * work fine so long as the underscores are done one at a time, or
1374: * the underscores don't wrap lines. Control and meta characters
1375: * map to their special emacs equivalents.
1376: */
1377:
1378:
1379: xputl(cp,flg,col)
1380:
1381: register char *cp; /* string pointer */
1382: int flg; /* disposition flag */
1383: int col;
1384:
1385: /* Keywords: character-output the-screen-map:20 screen-handling conversions:50 underlining:20 the-screen-cursor:10 ^-and-M-processing:40 */
1386:
1387: {
1388: char cbuf[256]; /* line buffer */
1389: register int i;
1390: register int b;
1391: int mb;
1392: int a;
1393:
1394: mb = b = mcol; /* buffer pointer */
1395:
1396: while (1) {
1397: if (b > mb) mb = b;
1398: if (b > SCRWID) {
1399:
1400: /* Line has wrapped. Put a ! on the end, and wrap anything that is left
1401: * over to the next line */
1402:
1403: i = cbuf[SCRWID];
1404: a = cbuf[SCRWID+1];
1405:
1406: /* i is the character overwritten by the !, a is the character */
1407: /* overwritten by the EOM in cflush */
1408:
1409: if (mline>=SCRNLIN-1) {
1410:
1411: /* Wrap from last line on screen, fold back up and don't write in
1412: * the last position! */
1413: cflush(cbuf,SCRWID);
1414: mline--; /* don't run overboard */
1415: } else {
1416: cbuf[SCRWID]='!';
1417: cflush(cbuf,SCRWID+1);
1418: if (flg && PICMODE) {
1419: if (col>0) hrem = 1+column-col;
1420: return;
1421: }
1422: mline++;
1423: scrmap[mline] = scrow+SCRCNL; /* mark continuation */
1424: }
1425: mcol = 0;
1426: b = 0;
1427: while(b < LNOMOD*LNOWID) cbuf[b++] = ' ';
1428: cbuf[b++] = i;
1429: i = SCRWID+2;
1430: if (SCRWID+1<mb) cbuf[b++] = a;
1431: while (i < mb) {
1432: cbuf[b++] = cbuf[i++];
1433: }
1434: mb = b; /* RESET */
1435: }
1436:
1437: /* Process Next character */
1438:
1439: i = (*cp++)&0377; /* next char */
1440:
1441: if (flg) { /* if buffer invocation */
1442: if (col++ == column) {
1443: nln = mline;
1444: ncol = b;
1445: }
1446: if (i == EOL) {
1447: cflush(cbuf,mb);
1448: return; /* done */
1449: }
1450: } else {
1451: if (i == 0) {
1452: cflush(cbuf,mb);
1453: return; /* done */
1454: }
1455: if (i == NEWLINE) { /* embedded newline */
1456: cflush(cbuf,b);
1457: clrl();
1458: mb = b = 0;
1459: if (mline < SCRNLIN) mline++; /* don't overflow */
1460: scrmap[mline] = 0;
1461: mcol = 0;
1462: continue; /* re-loop */
1463: }
1464: }
1465:
1466: if ((i & META)&& (bit8== 0)) {
1467: cbuf[b++] ='M';
1468: cbuf[b++] = '-';
1469: if (b>mb) mb=b;
1470: i-= META;
1471: }
1472: reswitch: switch(ctype[i&0177]) {
1473: case UL:
1474: if (ULINE) i = 0200; /* terminal underlines */
1475:
1476: /* else just a plain old character */
1477:
1478: case PLAIN:
1479: if ((b < mb) && ((i & 0200) || (cbuf[b] & 0200))){
1480: i |= cbuf[b]; /* overstrike */
1481: }
1482: cbuf[b++] = i;
1483: break;
1484:
1485: case BACKSP:
1486: if (b>mcol) b--;
1487: break;
1488:
1489: /*Fall through to handle backspace in normal mode */
1490:
1491: case CONTRL:
1492:
1493: cbuf[b++] = '^';
1494: i = i^0100;
1495: goto reswitch; /* Handle things like ^_ correctly! */
1496: case TAB:
1497: i = TABSTOP-((b-(LNOMOD*LNOWID))%TABSTOP);
1498: while (i--) {
1499: cbuf[b++] = ' ';
1500: }
1501: break;
1502: }
1503: }
1504: }
1505:
1506: /* cput -- put a character in the file, like xputl */
1507:
1508:
1509: cput(c)
1510: register int c;
1511: /* Keywords: insertion help-messages ^-and-M-processing */
1512: {
1513: c &= 0377;
1514: if (c & META) {
1515: put('M');
1516: put('-');
1517: c-= META;
1518: }
1519: switch(ctype[c]) {
1520:
1521: case UL:
1522: case PLAIN:
1523: put(c);
1524: break;
1525: default:
1526: put('^');
1527: put(c^0100);
1528: break;
1529: }
1530: }
1531:
1532:
1533:
1534: /* clear the rest of the line, checking to see if the line previously
1535: * displayed corresponds to the one displayed here now */
1536:
1537: clrl()
1538: /* Keywords: prompting:10 display-format:20 informational-displays:30 screen-lines clearing */
1539: {
1540: register int x;
1541: register int y;
1542: register int z;
1543: char *xln;
1544: int xcol;
1545: #ifdef PC
1546: char buf[130];
1547: #endif
1548: x = mline;
1549: z = mcol;
1550: y = scrjnk[mline] - mcol;
1551: if (y > 0) {
1552: #ifdef PC
1553: buf[y]=0;
1554: for (x = 0; x < y; x++) buf[x] = ' ';
1555: x = mline;
1556: vout(mline,mcol,buf);
1557: #else
1558: sgo(mline,mcol); /* go for real */
1559: if (CLINE) {
1560: PUTS(CLINE);
1561: } else {
1562: xln = cmap[mline];
1563: xcol = mcol;
1564: while (y--) {
1565: if (xln[xcol] && xln[xcol] != ' ') {
1566: sgo(mline,xcol);
1567: putchar(' '); /* wipe line */
1568: if ((scrcol++ >= REALWID) && SCRWRAP) {
1569: scrlin++;
1570: scrcol=0;
1571: }
1572: }
1573: xcol++;
1574: }
1575: }
1576: #endif
1577: scrjnk[x] = z;
1578: }
1579: }
1580:
1581: /* findline -- find a line on the screen */
1582:
1583: /* findline makes no judgement as to whether or not the line is correct */
1584: /* whether or not the screen is OK up to the line */
1585:
1586: findline(line)
1587: register int line;
1588:
1589: /* Keywords: the-screen-cursor screen-lines screen-handling the-screen-map:10 */
1590:
1591: {
1592: register int i;
1593:
1594: if (disbuf[cwind] == curbf) {
1595: for (i = wbase; i < SCRLINES; i++) {
1596: if (scrmap[i] == line) {
1597: nln = i;
1598: return(1);
1599: }
1600: }
1601: }
1602: return(0);
1603: }
1604:
1605: /* find the screen address of a file */
1606:
1607: /* The result is to set mcol and mline and return 1 if found
1608: * found, otherwise 0 is returned */
1609:
1610:
1611: findpos(line,col)
1612:
1613: register char *line;
1614: register int col;
1615:
1616: /* Keywords: the-screen-cursor ^-and-M-processing:50 screen-lines screen-handling the-screen-map:10 picture-mode:10 */
1617: {
1618: register int i;
1619: char c;
1620:
1621: mcol = LNOMOD*LNOWID;
1622: i = 0;
1623: while (i < hcol) if (line[i++] == EOL) return(0);
1624: for (i = hcol; i < col; i++) {
1625: if ((c= line[i]) == EOL) return(0);
1626: if (c & META) mcol += metal;
1627: switch(ctype[c&0177]) {
1628:
1629: case PLAIN:
1630: case UL:
1631: mcol++;
1632: break;
1633: case BACKSP:
1634: if (mcol) mcol--;
1635: break;
1636: case CONTRL:
1637: mcol+=2;
1638: break;
1639: case TAB:
1640: mcol = mcol+TABSTOP-((mcol-(LNOMOD*LNOWID))%TABSTOP);
1641: break;
1642: }
1643: if (mcol>SCRWID) {
1644: if (PICMODE) {
1645: hrem = col-i;
1646: return(0);
1647: }
1648: if (++mline>SCRLINES) return(0);
1649: mcol = mcol-SCRWID;
1650: if (LNOMOD) mcol+= LNOWID;
1651: }
1652: }
1653: return(1);
1654: }
1655:
1656: /* The following function scans the text above "line" to compute
1657: * it's physical size. The scan continues until either hstop physical
1658: * screen lines are found or the line lstop is reached. The line at
1659: * which the scan stopped is returned, and the screen area is left
1660: * in the global "dsize" */
1661:
1662: areal(line,hstop,lstop)
1663: /* Keywords: screen-lines display-update:30 screen-handling */
1664:
1665:
1666: int line;
1667: int hstop;
1668: int lstop;
1669:
1670: {
1671: register char *lp;
1672: register int col;
1673: register int c;
1674:
1675: dsize = 0;
1676: while ((line > lstop) && (dsize < hstop)) {
1677: --line;
1678: dsize++;
1679: if (PICMODE) continue; /* Picture mode gets one line/line */
1680:
1681: lp = mkline(line);
1682: col = LNOMOD*LNOWID;
1683: while ((c = *lp++) != EOL) {
1684: if (c & META) col += metal;
1685: switch(ctype[c&0177]) {
1686:
1687: case PLAIN:
1688: case UL:
1689: col++;
1690: break;
1691: case BACKSP:
1692: if (col) col--;
1693: break;
1694: case CONTRL:
1695: col+=2;
1696: break;
1697: case TAB:
1698: col = col+TABSTOP-((col-(LNOMOD*LNOWID))%TABSTOP);
1699: break;
1700: }
1701: if (col>SCRWID) {
1702: dsize++;
1703: col = col-SCRWID;
1704: if (LNOMOD) col+= LNOWID;
1705: }
1706: }
1707: }
1708: return(line);
1709: }
1710:
1711: /* print a line number(x) */
1712:
1713: lnumb(x)
1714:
1715: /* Keywords: line-numbers informational-displays screen-handling */
1716: {
1717: register int i;
1718: char tbuf[8];
1719:
1720: for (i=0; i<8; i++) tbuf[i]=0;
1721: seprintf(tbuf,"%d",x);
1722: mcol = 0; /* make sure were at start of line */
1723:
1724: for (i=0; i<LNOWID; i++) {
1725: if (tbuf[i] == 0) tbuf[i] = ' ';
1726: }
1727: cflush(tbuf,LNOWID); /* output to terminal */
1728: }
1729: /* putin -- insert string into file */
1730:
1731:
1732: putin(xp)
1733:
1734: register char *xp;
1735:
1736: /* Keywords: informational-displays help-messages:50 error-messages:50 screen-handling */
1737: {
1738: register int c;
1739: RARE = 1;
1740: while (c = *xp++) {
1741: if (c == NEWLINE) { /* Note that NEWLINE != '\n' */
1742: nl(1);
1743: put(' ');
1744: }
1745: else put(c);
1746: }
1747: RARE = 0;
1748: }
1749:
1750: /* dspage -- re-position display with (line) first. If */
1751: /* the move argument is non-zero, the cursor is moved into the middle */
1752: /* of the new display */
1753:
1754: dspage(line,moves)
1755: int line;
1756: int moves;
1757:
1758: /* Keywords: commands display-update:30 the-screen-cursor scrolling */
1759: {
1760: if (line<1) {
1761: if (minln > 1) line=1;
1762: else {
1763: beep();
1764: return(0);
1765: }
1766: }
1767: if (line > nlines) {
1768: if (maxln < nlines) line = nlines;
1769: else {
1770: beep();
1771: return(0);
1772: }
1773: }
1774: fclear(); /* just blew up file */
1775: if (disbuf[cwind] != curbf) {
1776:
1777: /* NOTE: This is a pain! display is out of date because we were
1778: * called from a macro, If we don't do something here, disup will pick
1779: * a new window when we change buffers. What we do is not very
1780: * good, but it works?
1781: */
1782:
1783: if (junked || ((twowind == 0) && (CLINE == 0))) {
1784: clear(); /* dumb terminal or command */
1785: } else {
1786: xclear(); /* others, just clobber map */
1787: }
1788: disbuf[cwind] = curbf; /* avoid reset in disup */
1789: }
1790: minln = line;
1791: maxln = line+SCRLINES-wbase; /* This is just a guess, but should make it to disup all right. */
1792: if (maxln > nlines) maxln = nlines;
1793: if (moves) move((minln+maxln)/2,0);
1794: return(0);
1795: }
1796: /* nxtpag -- move to next page */
1797:
1798: nxtpage(count)
1799:
1800: register int count;
1801:
1802: /* Keywords: display-update:20 the-screen-cursor:30 movement commands forwards paging */
1803:
1804: {
1805:
1806: return(dspage((maxln+1+((count-1)*(SCRLINES-wbase)))-keepg,1));
1807: }
1808:
1809: /* move to top of page (current line becomes first line) */
1810:
1811: toppage()
1812:
1813: /* Keywords: display-update:20 the-screen-cursor:30 movement scrolling commands backwards */
1814: {
1815: dspage(curln,0);
1816: }
1817:
1818: /* move to previous page */
1819:
1820: lstpage(count)
1821:
1822: register int count;
1823:
1824: /* Keywords: display-update:20 the-screen-cursor:30 movement commands backwards upward-movement:50 paging */
1825: {
1826: return(dspage((minln-count*(SCRLINES-wbase))+keepg,1));
1827: }
1828:
1829: clear()
1830: /* Keywords: clearing screen-handling the-screen-map:40 terminal-parameters:20 terminal-initialization:30 */
1831: {
1832: register int i;
1833: #ifdef PC
1834:
1835: video(REG(SCRL_UP,0),REG(NORMATB,0),0,REG(SCRNLIN,SCRWID));
1836: #else
1837: PUTS(CLEAR);
1838: #endif
1839: for (i = 0; i < SCRNLIN; i++) scrmap[i] = scrjnk[i] = 0;
1840: scrlin = scrcol = mline = mcol = 0;
1841: disbuf[0]=disbuf[1]= -1;
1842: junked = minln = maxln = 0;
1843: if (timemd) disptime = 1; /* Wiped out time display */
1844: }
1845:
1846:
1847: /* didle (display idle) update display and idle for the specified time */
1848:
1849: didle(count)
1850:
1851: int count;
1852: {
1853: /* Keywords: macro-programming display-update:10 time-processing:20 screen-handling */
1854:
1855: if (count > 100) count = 100; /* limit to 10 seconds */
1856: pushin(NULL); /* make sure we will update */
1857: disup();
1858: mflush(stdout);
1859: #ifndef PC
1860: while (count--) PUTS (WAIT1);
1861: #endif
1862: inpop();
1863: }
1864:
1865: /* disup() update display. disup should be called whenever you want the */
1866: /* to be up to date. disup does not update if there is more input */
1867: /* available from the current input source. */
1868:
1869: /* This is the high level display algorithm, which translates the
1870: * buffer into a screen image. The pparameters affecting the algorithm are
1871: *
1872: * scrmap[SCRNLIN] map from the display line to the file line on
1873: * that line of the display.
1874: * fmap[SCRNLIN] map from the file indicating what the smallest
1875: * column in the file containing undisplayed changes
1876: * is. A special value (LGOOD) indicates that
1877: * the whole line is good. This avoids looking at
1878: * the lines in the file that are known to be ok.
1879: * minln The file line appearing at the top of the current
1880: * window.
1881: * maxln The last file line appearing in this window.
1882: * lastln The screen line on which maxln is displayed.
1883: * curbf[2] The buffer displayed in each window.
1884: * dahead Flag indicating that we are displaying the line
1885: * with the cursor ahead of schedule.
1886: *
1887: * The basic algorithm is to firsst check to see if the window is properly
1888: * positioned to hold the cursor. If not, a new window is chosen and minln
1889: * reset. Then, each line that should be displayed is examined for
1890: * changes. Any lines needing updating are redisplay. A side effect of
1891: * the scan is to find the screen address of the current line. If the
1892: * screen address is found, the mode line and window splitting line are
1893: * updated (if necessary), and any other lines are blanked. If the cursor
1894: * wasn't found, it tries once again to display starting with the current
1895: * line. This can happen only if the line before the current line or the
1896: * current line is gigantic, wrapping lots of times around the screen.
1897: * Repeated failures signal a fatal error and indicate a bug or an
1898: * enormous current line.
1899: */
1900:
1901: /* status display */
1902:
1903: char mdchar[2] = {'=', '>'};
1904:
1905:
1906: disup() /* force update display */
1907:
1908: {
1909:
1910: /* Keywords: clearing:5 screen-handling display-update scrolling:10 insertion:10 deletion:10 */
1911:
1912: /* Keywords: lookahead:20 the-screen-cursor:20 the-screen-map:20 screen-lines:10 mode-line:20 macro-hooks:10 */
1913: register int col;
1914: int fixed;
1915: register char *cp;
1916: long pm;
1917: int *fmp;
1918: int dahead;
1919: char pmbuf[10];
1920: char hcbuf[10];
1921: char smap[NSCRLIN];
1922: int smapped;
1923:
1924: if (MOREIN) return;
1925: fixed = smapped = 0 ;
1926: dahead = 0;
1927: nln = ncol = hrem = -1;
1928:
1929: /* Check to see if what is on the screen is from the same buffer. If
1930: * not, don't try to re-use it
1931: */
1932: if (disbuf[cwind] != curbf) {
1933: minln = 0; /* force repositioning */
1934: if (CLINE || twowind) {
1935: xclear(); /* force redisplay */
1936: } else {
1937: clear(); /* try to optimize dumb terminal */
1938: }
1939: disbuf[cwind] = curbf; /* mark buffer up to date */
1940: }
1941:
1942: /* See if the current line is on the screen. The check is not absolutely
1943: * perfect. If the current line is not on the screen, a new position
1944: * is picked. Mis-guessing will be caught eventually.
1945: */
1946:
1947:
1948: if ((minln == 0) ||(curln <minln) || ((curln> maxln) && (curln-maxln+lastln>=SCRLINES))) {
1949:
1950: /* display position is bad */
1951:
1952: if (junked) {
1953: clear();
1954: disbuf[cwind] = curbf; /* mark buffer up to date */
1955: }
1956: badpos:
1957: if (hrem>0) {
1958: hcol = hcol+4+(hrem-hrem%4);
1959: hrem = -1;
1960: fclear();
1961: goto retry;
1962: }
1963: if(fixed++) {
1964: if (fixed > 2) error(FATAL,42); /* can't find cursor */
1965: minln = curln;
1966: } else {
1967: minln = areal(curln,(SCRLINES-wbase)/2,1);
1968: }
1969: fclear(); /* file bad */
1970: if (SCREG || LOPEN) {
1971: if ((minln > 1) && (minln < curln)) dahead = wbase+dsize;
1972: }
1973: maxln = curln;
1974: }
1975:
1976: if (column<hcol) {
1977: hcol = column-column%4;
1978: dispmod();
1979: fclear();
1980: }
1981:
1982: /* Now for the real work, check all of the lines. A line can be bad if
1983: * scrmap indicates that its not in the right place on the display
1984: * or if fmap indicates that it may have changed since being put up.
1985: */
1986:
1987: retry: fmp = &fmap[-minln];
1988: mcol = 0;
1989: for (scrow = minln, mline = wbase; (scrow <= nlines) && (mline < SCRLINES);scrow++) {
1990: if (scrmap[mline] != scrow) {
1991:
1992: /* line is bad, first try to bring it into position by scrolling or by
1993: * inserting/deleting lines. This could result in the display being
1994: * corrected.
1995: */
1996: #ifndef PC
1997: if ((smapped == 0) && (LOPEN || (SSCROLL && (mline == 0)))) {
1998:
1999:
2000: /* There is some hope for scrolling, build the display map. */
2001: /* We scan remaining screen lines for ones that may be of use. */
2002:
2003: /* smap[line-minln] = screen line (if any) */
2004: /* scrmap[line] = 0 if known to be useless */
2005:
2006: register int x;
2007:
2008: for (x = 0; x < SCRLINES; x++) smap[x] = 0;
2009: smapped = scrow+SCRLINES-mline-1;
2010: for (x = mline+1; x < SCRLINES; x++) {
2011: col = scrmap[x];
2012: if ((col & SCRCNL) == 0) {
2013: if ((col<scrow) || (col > smapped)) {
2014: scrmap[x] = 0; /* Useless */
2015: } else {
2016: smap[col-minln] = x;
2017: }
2018: }
2019: }
2020: }
2021:
2022: /* try to scroll the screen up with newlines */
2023:
2024: if ((mline == 0) && SSCROLL && (col=smap[scrow-minln])) {
2025: sscroll(col);
2026: smapped = 0;
2027: } else if(LOPEN) {
2028:
2029: /* try to adjust screen by
2030: * opening and closing lines */
2031:
2032: if (col=smap[scrow-minln]) {
2033: vadjust(mline-col,mline);
2034: smapped = 0;
2035: } else if (((col=scrmap[mline]&SCRMSK)>scrow) && (col <= nlines)) {
2036: smapped = areal(col,SCRLINES-mline,scrow);
2037: vadjust(dsize,mline);
2038: smapped = 0;
2039: }
2040: }
2041:
2042: #endif
2043: goto fixline;
2044: }
2045: if (fmp[scrow] < LGOOD) {
2046:
2047: fixline:
2048:
2049: /* Check for display-ahead. If we are on the first line, jump ahead
2050: * to the current line and show it first, being careful to return
2051: * when appropriate */
2052:
2053:
2054: if (dahead>0) {
2055:
2056: /* Pick line for display ahead. Note that in some cases, the
2057: * current line is on the screen, in which case we just use it. If
2058: * not, we try the middle of the screen. If this is marked as
2059: * belonging to some other line, we just ignore dahead. */
2060:
2061: if (findline(curln)) mline = nln;
2062: else {
2063: if (scrmap[dahead]) {
2064: dahead = 0;
2065: goto disline;
2066: }
2067: if ((scrmap[dahead-1]&SCRMSK) != curln-1) {
2068: mgo(dahead-1,0);
2069: scrmap[mline]=0;
2070: clrl();
2071: }
2072: if ((scrmap[dahead+1]&SCRMSK) != curln+1) {
2073: mgo(dahead+1,0);
2074: scrmap[mline]=0;
2075: clrl();
2076: }
2077: mline = dahead;
2078: }
2079: dahead = -1;
2080: scrow = curln;
2081: }
2082: disline:
2083:
2084: /* Now fix the display of this line. fmap indicates where we start */
2085:
2086:
2087: cp = mkline(scrow);
2088: if ((scrmap[mline] == scrow) && (col =fmp[scrow])) {
2089: if (col == LGOOD) goto skipit;
2090: if ((scrow == curln) && (col > column)) {
2091: col = column;
2092:
2093: }
2094:
2095: /* Note that if we have backspace mode on, then we can't start the
2096: * line in the middle, because the line may have backspaces that
2097: * span the cursor, or have had them in its previous form. The only
2098: * safe thing to do is re-format the whole thing and let cflush
2099: * throw most of it away. */
2100:
2101: if ((col == 0) || BACKP) goto numbline;
2102: if (col<hcol) col=hcol;
2103: if (findpos(cp,col)==0) goto badpos;
2104: cp +=col;
2105: } else {
2106: scrmap[mline] = scrow; /* mark line */
2107: numbline: if(LNOMOD) lnumb(scrow);
2108: col = 0;
2109: while (col < hcol) {
2110: if (*cp==EOL) break;
2111: cp++;
2112: col++;
2113: }
2114: }
2115: xputl(cp,1,((curln==scrow)?col:-1000)); /* process line */
2116: clrl();
2117: mline++;
2118: mcol = 0;
2119: fmp[scrow] = LGOOD;
2120:
2121: /* if we have NDELAY I/O available, see if there is any type ahead */
2122:
2123: if (((int) _stdout._cnt *ttywarp) > PATIENCE) {
2124: ttfill(); /* try to fill tty buffer */
2125: if (MOREIN) {
2126: clptr = mkline(curln);
2127: if (maxln < scrow) maxln = scrow;
2128: return;
2129: }
2130: }
2131:
2132: } else {
2133:
2134: /* line on the screen is OK, see if the current cursor position is in it */
2135:
2136:
2137: skipit: if (scrow == curln) {
2138: cp = mkline(curln);
2139: if (findpos(cp,column)) {
2140: nln = mline;
2141: ncol = mcol;
2142: } else {
2143: goto badpos;
2144: }
2145: }
2146: mline++;
2147: while ((scrmap[mline]) == (scrow|SCRCNL)) mline++;
2148: mcol = 0;
2149: }
2150: if (dahead<0) {
2151: dahead = 0;
2152: nln = -1; /* Make sure we find this line later */
2153: mline = wbase;
2154: scrow = minln;
2155: goto disline; /* If displaying ahead, return to finish display */
2156: }
2157: /* done re-creating the display, now clean up the rest of the lines */
2158:
2159: }
2160: maxln = scrow-1; /* last line on the screen */
2161: wminln[cwind] = minln;
2162: wmaxln[cwind] = maxln;
2163: lastln = mline-1; /* last display line used */
2164:
2165: if (twowind && (mline == SCRLINES) && (cwind == 0)) {
2166: prompt(mline,endput);
2167: scrmap[mline]=0;
2168: }
2169: if ((scrow > nlines) || (mline == SCRLINES)) {
2170: while (mline < SCRLINES+1) {
2171: if ((twowind == 0) || (mline < SCRLINES) || cwind) {
2172: if (scrjnk[mline])clrl();
2173: scrmap[mline++]=0;
2174: } else mline++;
2175: }
2176: }
2177: if (nln < 0) {
2178: goto badpos; /* oops, blew it agaiin */
2179: }
2180: if ((scrmap[MODLN] != MODHACK)||PMODE) {
2181:
2182: /* Pre-format sections for display-percent mode and horizontal scrolling */
2183:
2184: if (hcol) {
2185: seprintf(hcbuf,"<%d ",hcol);
2186: } else hcbuf[0] = 0;
2187: if (PMODE) {
2188: pm = (nlines == 1)?1:nlines-1;
2189: pm = (100L*((long) curln-1))/pm;
2190: seprintf (pmbuf," %D%%",pm);
2191: } else pmbuf[0] = 0;
2192: if (hooks[Mode_Line_Hook]) {
2193: hook(Mode_Line_Hook);
2194: retrvs(fnbuf,FNLEN);
2195: prompt(MODLN,"%s",fnbuf);
2196: } else {
2197:
2198: prompt(MODLN,"%s%s %s (%d) %s %c %s%s",hcbuf,myname,version,bfnumb(),bname(),mdchar[modded()], fname(),pmbuf);
2199: }
2200: if (lgripe && (infrn == 0)) {
2201: prompt(ECHOL,"I can only use %d lines by %d columns of your screen",SCRNLIN,SCRWID+1);
2202: lgripe = 0;
2203: }
2204: scrmap[MODLN] = MODHACK;
2205: if (twowind) {
2206: col = w1base-1;
2207: prompt(col,endput);
2208: scrmap[col] = 0; /* SPPML */
2209: }
2210: mgo(nln,ncol); /* Restore cursor */
2211: }
2212: clptr = mkline(curln); /* make sure we get this one */
2213: mgo(nln,ncol);
2214: }
2215:
2216: /* Initialize screen size */
2217:
2218: setsize()
2219: /* Keywords: modes:50 screen-handling display-format terminal-initialization:10 */
2220: {
2221:
2222: /* Set safe defaults for height and width, and set dependent parameters */
2223:
2224: if (SCRNLIN<=4) SCRNLIN=5;
2225: if (SCRNLIN>NSCRLIN) {
2226: SCRNLIN=NSCRLIN;
2227: lgripe++;
2228: }
2229: if (SCRWID>NSCRCOL-1) {
2230: lgripe++;
2231: SCRWID=NSCRCOL-1;
2232: }
2233: if (SCRWID > REALWID) {
2234: lgripe++;
2235: SCRWID = REALWID;
2236: }
2237: SCRLINES=SCRNLIN-4;
2238: ECHOL = SCRNLIN-1;
2239: MODLN = SCRNLIN-3;
2240: }
2241:
2242: /* display the mode line */
2243:
2244: dispmod()
2245: /* Keywords: mode-line */
2246: {
2247: scrmap[MODLN] = 0;
2248: }
2249:
2250:
2251: ttype() /* set terminal type */
2252:
2253: {
2254: /* Keywords: commands terminal-initialization terminal-modes:20 terminal-parameters:50 */
2255:
2256: register char *mp;
2257: #ifndef PC
2258: mp = expenv(getname("Terminal Type? "));
2259: if (mp == NULL) return;
2260: sttype(mp);
2261: #endif
2262: }
2263: #if defined(TERMCAP) || defined(TERMINFO)
2264: /* Like putchar but a function which can be passed to putpad */
2265: pchar(c)
2266: {
2267: putchar(c);
2268: }
2269: /*
2270: * Print out string str with padding.
2271: */
2272: putpad(str)
2273: char *str;
2274: {
2275: if (str) {
2276: tputs(str, SREGION, pchar);
2277: }
2278: }
2279:
2280: #endif
2281: #if defined(TERMINFO)
2282:
2283: sttype(mp)
2284: register char *mp;
2285: {
2286: #ifndef SINGLE
2287: extern struct term _first_term; /* statically allocated terminal structure */
2288: #endif
2289: char tbuf[1024];
2290: static char bufspace[512];
2291: char *xp;
2292: char *pt = bufspace;
2293: int rc = 1;
2294:
2295: cur_term = 0; /* Force setupterm to use default */
2296: if (mp == NULL) mp = dumbterm;
2297: setupterm(mp, 1, &rc);
2298: if (rc != 1) {
2299: if (mp == dumbterm) {
2300: write(1,"\n\r\n\rI Can't understand your terminal type\n\r",43);
2301: quit();
2302: }
2303: cur_term = & _first_term; /* Restore terminal pointer */
2304: IGNORE(error(WARN,86,mp,em_dir));
2305: return;
2306: }
2307: UP = cursor_up;
2308: RELUP = parm_up_cursor;
2309: DOWN = cursor_down;
2310: if (DOWN == NULL)
2311: DOWN = "\n";
2312: RELDOWN = parm_down_cursor;
2313: BACK = cursor_left;
2314: RELBACK = parm_left_cursor;
2315: FORWARD = cursor_right;
2316: RELFORW = parm_right_cursor;
2317: CLEAR = clear_screen;
2318: CLINE = clr_eol;
2319: BELL = bell;
2320: CURAD = cursor_address;
2321: NOP = pad_char;
2322: LOPEN = insert_line;
2323: CLOPEN = parm_insert_line;
2324: LDEL = delete_line;
2325: CLDEL = parm_delete_line;
2326: INSERTC = insert_character;
2327: INSERTM = enter_insert_mode;
2328: OSERTC = exit_insert_mode;
2329: INSERTP = insert_padding;
2330: IN = insert_null_glitch;
2331: /*
2332: DELMODE = enter_delete_mode; /* Note that DM is a flag in emacs * /
2333: */
2334: DELC = delete_character;
2335: RSCROLL = scroll_reverse;
2336: SSCROLL = scroll_forward;
2337: CLSCROLL= parm_index;
2338: CRSCROLL= parm_rindex;
2339: if ((SSCROLL == NULL) && (!eat_newline_glitch)) SSCROLL = "\n";
2340: SCREG = change_scroll_region;
2341:
2342: /* UNDERLINING */
2343:
2344: if (transparent_underline) {
2345: ULINE = "%c_"; /* underline this way */
2346: EOVER = erase_overstrike;
2347: }
2348: else if (underline_char) {
2349: /* underscore by magic word */
2350: ULINE = pt;
2351: pt = strcpy(pt,"%c");
2352: pt = strcpy(pt,underline_char);
2353: EOVER = !ceol_standout_glitch;
2354: pt++;
2355: } else if (xp = enter_underline_mode) { /* underscore mode */
2356: ULINE=xp;
2357: UEND= exit_underline_mode;
2358: EOVER = !ceol_standout_glitch;
2359: }
2360: CR = carriage_return;
2361: SCINIT = enter_ca_mode;
2362: VEXIT = exit_ca_mode;
2363: MI = move_insert_mode;
2364: if ((CURAD == NULL) && (CURAD = cursor_mem_address)) SSCROLL=NULL;
2365:
2366: /* Use memory addressing and no scrolling if forced */
2367:
2368: SCRWID = columns - 1;
2369: SCRNLIN = lines;
2370: SCRWRAP = auto_right_margin;
2371: #ifdef JWINSIZE
2372:
2373: /*
2374: * Courtesy of Mark Horton - CDB
2375: *
2376: * ioctls for Blit - you may need to #include <jioctl.h>
2377: * This ioctl defines the window size and overrides what
2378: * it says in the terminal description file.
2379: */
2380: {
2381: struct jwinsize w;
2382:
2383: if (ioctl(1, JWINSIZE, &w) != -1) {
2384: SCRNLIN = w.bytesy;
2385: SCRWID = w.bytesx - 1;
2386: }
2387: }
2388: if (getenv ("LINES"))
2389: IGNORE (nscan (getenv ("LINES"), &SCRNLIN));
2390: if (getenv ("COLUMNS"))
2391: {
2392: IGNORE (nscan (getenv ("COLUMNS"), &SCRWID));
2393: SCRWID--;
2394: }
2395:
2396: #endif
2397: REALWID=SCRWID;
2398: REALBOT=SCRNLIN;
2399: setsize();
2400: if (IN) BLANK= 0;
2401: else BLANK= ' ';
2402: if (VCOST == 0) VCOST = 1;
2403: if (CURAD) {
2404: acost = dcost(CURAD);
2405: } else {
2406: acost = dcost(RELUP)+dcost(RELFORW);
2407: }
2408: dccost = dcost(DELC);
2409: if (INSERTM) iccost = dcost(INSERTM)+dcost(OSERTC);
2410: else iccost = dcost (INSERTC);
2411: lUP = dcost(UP);
2412: lDOWN = dcost(DOWN);
2413: lBAK = dcost(BACK);
2414: lCR = dcost(CR);
2415: if ((NOP == NULL) || (*NOP == 0)) NOP = "\200"; /* null pads get lost */
2416: if (ULINE) BACKP = 1; /* Set backspace mode if terminal underscores */
2417: vinit();
2418: TERMIQ = 0; /* Compute terminal's IQ */
2419: if (CURAD) TERMIQ += 1;
2420: if (CLINE) TERMIQ += 2;
2421: if (LOPEN || SCREG) TERMIQ += 4;
2422: if (INSERTC || INSERTM) TERMIQ += 8;
2423: clear();
2424: }
2425:
2426: /* for costing out terminfo capabilities */
2427: static int TIcount;
2428: /*ARGSUSED*/
2429:
2430: int TIcost(c)
2431: char c;
2432: {
2433: ++TIcount;
2434: }
2435: #else
2436: #ifdef TERMCAP
2437:
2438: char PC;
2439: char *BC;
2440: char *TE;
2441:
2442: sttype(mp)
2443: register char *mp;
2444: {
2445: char tbuf[1024];
2446: static char bufspace[512];
2447: char *xp;
2448: char *pt = bufspace;
2449: char *tgetstr();
2450: if (mp == NULL) mp = dumbterm;
2451: if (tgetent(tbuf, mp) < 1) {
2452: if (mp == dumbterm) {
2453: write(1,"\n\r\n\rI Can't understand your terminal type\n\r",43);
2454: quit();
2455: }
2456: IGNORE(error(WARN,86,mp,em_dir));
2457: return;
2458: }
2459: UP = tgetstr("up", &pt);
2460: DOWN = tgetstr("do", &pt);
2461: if (DOWN == NULL)
2462: DOWN = "\n";
2463: BACK = tgetstr("bc", &pt);
2464: if (BACK == NULL && tgetflag("bs"))
2465: BACK = "\b";
2466: BC = BACK;
2467: FORWARD = tgetstr("nd", &pt);
2468: CLEAR = tgetstr("cl", &pt);
2469: CLINE = tgetstr("ce", &pt);
2470: BELL = "\7";
2471: CURAD = tgetstr("cm", &pt);
2472: NOP = tgetstr("pc", &pt);
2473: if(NOP != NULL) PC = *NOP;
2474: LOPEN = tgetstr("al", &pt);
2475: CLOPEN = tgetstr("AL", &pt);
2476: LDEL = tgetstr("dl", &pt);
2477: CLDEL = tgetstr("DL", &pt);
2478: INSERTC = tgetstr("ic", &pt);
2479: INSERTM = tgetstr("im", &pt);
2480: OSERTC = tgetstr("ei", &pt);
2481: INSERTP = tgetstr("ip", &pt);
2482: IN = tgetflag("in", &pt);
2483: DELMODE = (tgetstr("dm", &pt)==NULL); /* Note that DM is a flag in emacs */
2484: DELC = tgetstr("dc", &pt);
2485: RSCROLL = tgetstr("sr", &pt);
2486: SSCROLL = tgetstr("nl", &pt);
2487: CLSCROLL = tgetstr("SF", &pt);
2488: if (SSCROLL == NULL) SSCROLL = tgetstr("sf",&pt);
2489: if ((SSCROLL == NULL) && (tgetflag("xn")== NULL)) SSCROLL = "\n";
2490: SCREG = tgetstr("cs", &pt);
2491:
2492: /* UNDERLINING */
2493:
2494: if (tgetflag("ul")) {
2495: ULINE = "%c_"; /* underline this way */
2496: EOVER = tgetflag("eo");
2497: }
2498: else if (xp = tgetstr("uc",&pt)) {
2499: /* underscore by magic word */
2500: ULINE = pt;
2501: pt = mstrcpy(pt,"%c");
2502: pt = mstrcpy(pt,xp);
2503: EOVER = (tgetflag("xs") == 0);
2504: pt++;
2505: } else if (xp = tgetstr("us",&pt)) { /* underscore mode */
2506: ULINE=xp;
2507: UEND= tgetstr("ue",&pt);
2508: EOVER = (tgetflag("xs") == 0);
2509: }
2510: CR = tgetstr("cr", &pt);
2511: if (CR == NULL) {
2512: if (tgetflag("nc") == 0) CR = "\015";
2513: }
2514: SCINIT = tgetstr("ti", &pt);
2515: TE = tgetstr("up", &pt);
2516: MI = tgetflag("mi", &pt);
2517: SCRWID = tgetnum("co") - 1;
2518: SCRNLIN = tgetnum("li");
2519: SCRWRAP = tgetflag("am");
2520: #ifdef JWINSIZE
2521:
2522: /*
2523: * Courtesy of Mark Horton - CDB
2524: *
2525: * ioctls for Blit - you may need to #include <jioctl.h>
2526: * This ioctl defines the window size and overrides what
2527: * it says in the terminal description file.
2528: */
2529: {
2530: struct jwinsize w;
2531:
2532: if (ioctl(1, JWINSIZE, &w) != -1) {
2533: SCRNLIN = w.bytesy;
2534: SCRWID = w.bytesx - 1;
2535: }
2536: }
2537: if (getenv ("LINES"))
2538: IGNORE (nscan (getenv ("LINES"), &SCRNLIN));
2539: if (getenv ("COLUMNS"))
2540: {
2541: IGNORE (nscan (getenv ("COLUMNS"), &SCRWID));
2542: SCRWID--;
2543: }
2544:
2545: #endif
2546: REALWID=SCRWID;
2547: REALBOT=SCRNLIN;
2548: setsize();
2549: if (VCOST == 0) VCOST = 1;
2550: if (IN) BLANK= 0;
2551: else BLANK= ' ';
2552: if (CURAD) {
2553: acost = dcost(CURAD);
2554: } else {
2555: acost = dcost(RELUP)+dcost(RELFORW);
2556: }
2557: dccost = dcost(DELC);
2558: if (INSERTM) iccost = dcost(INSERTM)+dcost(OSERTC);
2559: else iccost = dcost (INSERTC);
2560: lUP = dcost(UP);
2561: lDOWN = dcost(DOWN);
2562: lBAK = dcost(BACK);
2563: lCR = dcost(CR);
2564: if (SCREG) LOPEN = SCREG; /* make sure we use SCREG */
2565: if ((NOP == NULL) || (*NOP == 0)) NOP = "\200"; /* null pads get lost */
2566: if (ULINE) BACKP = 1; /* Set backspace mode if terminal underscores */
2567: vinit(); /* Initialize screen */
2568:
2569: TERMIQ = 0; /* Compute terminal's IQ */
2570: if (CURAD) TERMIQ += 1;
2571: if (CLINE) TERMIQ += 2;
2572: if (LOPEN || SCREG) TERMIQ += 4;
2573: if (INSERTC || INSERTM) TERMIQ += 8;
2574: clear();
2575: }
2576: #else
2577: #ifndef PC
2578:
2579: /* terminal description file parser: */
2580:
2581: /* terminal description file contains lines with
2582:
2583: parameter=data
2584:
2585: * where data is either a number of a string */
2586:
2587:
2588: ttyparse(mp)
2589: char *mp;
2590:
2591: /* Keywords: conversions:20 terminal-parameters terminal-initialization reading */
2592:
2593: {
2594: register FILE *file;
2595: char xbuf[128];
2596: FILE ttyfile[1];
2597: #define OPTSIZE 256
2598: char optbuf[OPTSIZE];
2599: register char *cp;
2600: register int c;
2601: #ifdef PORTEXT
2602: int parmp;
2603: #else
2604: int *parmp;
2605: #endif
2606: int parm;
2607:
2608:
2609: /* find the terminal file and open it */
2610:
2611: if (mp) {
2612: seprintf(xbuf,"%s/terminals/%s",em_dir,mp); /* terminal file */
2613: file = xopen(ttyfile,xbuf,"r");
2614: if (file == NULL) {
2615: file = xopen(ttyfile,mp,"r"); /* Try full pathname */
2616: }
2617: if (file == NULL) {
2618: badterm: error (WARN,43,mp,em_dir);
2619: return(0);
2620: }
2621: } else {
2622:
2623: /* This code restores the terminal to a "sane" default */
2624:
2625: file = ttyfile;
2626: ttyfile[0]._frn = open("/dev/null",0);
2627: ttyfile[0]._cnt = lng(nulltty);
2628: ttyfile[0]._ptr = nulltty;
2629: }
2630: /* first find what option we are setting */
2631:
2632: nextparm: cp = optbuf;
2633: while ((c = getc(file)) != '=') {
2634: if (c == '\n') goto nextparm; /* comment line */
2635: if (c == EOF) {
2636: mclose(file);
2637: return(1); /* abort during option scan */
2638: }
2639: if (cp-optbuf >= OPTSIZE) goto badterm; /* OOPS! */
2640: *cp++=c;
2641: }
2642: *cp = 0;
2643:
2644: /* look up parameter in parameter table */
2645:
2646: #ifdef PORTEXT
2647: for (parmp = 0, cp = ttydata; *cp; parmp++,cp+=2) {
2648: #else
2649: for (parmp = ((int * )&UP), cp = ttydata; *cp; parmp++,cp+=2) {
2650: #endif
2651: if ((optbuf[0]==cp[0])&& (optbuf[1]==cp[1])) {
2652:
2653: c = getc(file);
2654: if ((c >= '0') && (c <= '9')) {
2655: parm = 0;
2656: while ((c >= '0') && (c <= '9')) {
2657: parm = 10*parm + (c-'0');
2658: c = getc(file);
2659: }
2660: #ifdef PORTEXT
2661: *(parmptr[parmp]) = parm;
2662: #else
2663: *parmp = parm;
2664: #endif
2665: if (c != EOF) goto nextparm;
2666: mclose(file);
2667: return(1);
2668: }
2669: #ifdef PORTEXT
2670: *(parmptr[parmp]) = ((int) &ttystrings[ttyptr]);
2671: #else
2672: *parmp = ((int) &ttystrings[ttyptr]);
2673: #endif
2674: while ((c != EOF) && (c != EOL)) {
2675: if (c == '\\') {
2676: c = getc(file);
2677: if (c == 'n') c = '\n';
2678: }
2679:
2680: ttystrings[ttyptr++] = c;
2681: c = getc(file);
2682: }
2683: ttystrings[ttyptr++] = 0;
2684: if (c != EOF) goto nextparm;
2685: }
2686: }
2687: /* error(WARN,68,optbuf); Don't complain about non-existent capabilities */
2688:
2689: goto nextparm;
2690: }
2691: #endif
2692: sttype(mp)
2693: register char *mp;
2694:
2695: /* Keywords: terminal-parameters terminal-initialization terminal-modes:20 string-handling:20 statistics:10 */
2696:
2697:
2698:
2699: {
2700: #ifdef PORTEXT
2701: int parmp;
2702: #else
2703: int *parmp;
2704: #endif
2705: /* First, initialize the tty data */
2706:
2707: ttyptr = 0;
2708: #ifdef PORTEXT
2709: for (parmp = 0; parmptr[parmp]; parmp++) {
2710: *(parmptr[parmp])=0;
2711: }
2712: #else
2713: for (parmp = ( (int *) &UP); parmp <= &DELMODE; parmp++) {
2714: *parmp=0;
2715: }
2716: #endif
2717: #ifdef PC
2718:
2719: SCRWID = 79;
2720: SCRNLIN = 24;
2721: ECHOL = 23;
2722: MODLN = 21;
2723: SCRLINES = 20;
2724: CLINE = "";
2725: clear();
2726: #else
2727: if (ttyparse(mp)) {
2728:
2729: #ifdef JWINSIZE
2730:
2731: /*
2732: * Courtesy of Mark Horton - CDB
2733: *
2734: * ioctls for Blit - you may need to #include <jioctl.h>
2735: * This ioctl defines the window size and overrides what
2736: * it says in the terminal description file.
2737: */
2738: {
2739: struct jwinsize w;
2740:
2741: if (ioctl(1, JWINSIZE, &w) != -1) {
2742: SCRNLIN = w.bytesy;
2743: SCRWID = w.bytesx;
2744: }
2745: }
2746: /*
2747: if (getenv ("LINES"))
2748: IGNORE (nscan (getenv ("LINES"), &SCRNLIN));
2749: if (getenv ("COLUMNS"))
2750: {
2751: IGNORE (nscan (getenv ("COLUMNS"), &SCRWID));
2752: }
2753: */
2754: #endif
2755: SCRWID--;
2756: REALWID=SCRWID;
2757: REALBOT=SCRNLIN;
2758: setsize();
2759: if (IN) BLANK= 0;
2760: else BLANK= ' ';
2761: if (VCOST == 0) VCOST = 1;
2762: if (CURAD) {
2763: acost = dcost(CURAD);
2764: } else {
2765: acost = dcost(RELUP)+dcost(RELFORW);
2766: }
2767: dccost = dcost(DELC);
2768: if (INSERTM) iccost = dcost(INSERTM)+dcost(OSERTC);
2769: if (INSERTM) iccost = 1;
2770: else iccost = dcost (INSERTC);
2771:
2772: lUP = dcost(UP);
2773: lDOWN = dcost(DOWN);
2774: lBAK = dcost(BACK);
2775: lCR = dcost(CR);
2776: if (ULINE) BACKP = 1; /* Set backspace mode if terminal underscores */
2777: if (OSERTC && (INSERTM == 0)) {
2778: INSERTM=INSERTC; /* old style insert modes */
2779: INSERTC=0;
2780: }
2781: if (SCREG) LOPEN = SCREG; /* make sure we use SCREG */
2782: if ((NOP == NULL) || (*NOP == 0)) NOP = "\200"; /* null pads get lost */
2783: vinit();
2784: TERMIQ = 0; /* Compute terminal's IQ */
2785: if (CURAD) TERMIQ += 1;
2786: if (CLINE) TERMIQ += 2;
2787: if (LOPEN || SCREG) TERMIQ += 4;
2788: if (INSERTC || INSERTM) TERMIQ += 8;
2789:
2790: clear();
2791: }
2792: #endif
2793: }
2794: #endif
2795: #endif
2796: #ifndef PC
2797: /* dcost -- calculate display cost of a string */
2798:
2799: dcost(sp)
2800: register char *sp;
2801: {
2802: /* Keywords: terminal-parameters terminal-initialization */
2803: register int dc;
2804: char dcbuf[512]; /* buffer for string */
2805:
2806: if (sp == NULL) return(1000); /* infinite cost for missing capability */
2807: #ifdef TERMINFO
2808: TIcount=0;
2809: tputs(tparm(sp,10,10),10,TIcost);
2810: return(TIcount);
2811: #else
2812: #ifdef TERMCAP
2813: dc = 0;
2814: while (*sp) {
2815: if (*sp++ != '%') dc++;
2816: }
2817: return(dc);
2818: #else
2819: seprintf(dcbuf,sp,10,10); /* expand a 'typical' example */
2820: return(lng(dcbuf)); /* return its length */
2821: #endif
2822: #endif
2823: }
2824: #endif
2825: /* yes or no question */
2826: /*VARARGS1*/
2827: int
2828: gyn(string,arg1)
2829:
2830: char *string;
2831: char *arg1;
2832: {
2833: /* Keywords: prompting user-interface yes-no-questions */
2834:
2835: register char c;
2836:
2837: while (1) {
2838: prompt2(ECHOL,string,&arg1);
2839: sgo(mline,mcol);
2840: if (infrn < 0) {
2841: pushin(NULL);
2842: c = getchar();
2843: inpop();
2844: } else c = getchar();
2845: donttime = 0; /* Re-enable time mode */
2846: switch(c) {
2847:
2848: case 'y':
2849: case 'Y':
2850: case ' ':
2851: return(1);
2852: case CTRLZ: /* This is necessary to insure exit */
2853: case 'n':
2854: case 'N':
2855: case RUBOUT:
2856: unprompt();
2857: return(0);
2858: case CTRLG:
2859: unprompt();
2860: return(-1);
2861: default:
2862: donttime = 1; /* Avoid time mode */
2863: prompt3("y for yes, n for no, ^G to quit");
2864: }
2865: }
2866: };
2867:
2868: /* beep -- obvious */
2869:
2870: beep()
2871:
2872: {
2873:
2874: /* Keywords: bell-ringing terminal-parameters:20 commands:20 error-messages:10 */
2875:
2876: #ifdef PC
2877:
2878: if (!NOBEL) video(REG(WR_TTY,BELL),REG(PAGE_0,NORMATB),0,0);
2879:
2880:
2881: #else
2882: if (!NOBEL) PUTS(BELL); /* print a bell */
2883: #endif
2884: }
2885:
2886: /* mtop -- move to top of display for message output */
2887:
2888: mtop()
2889: {
2890: /* Keywords: the-screen-cursor informational-displays MORE-processing */
2891: mgo(0,0); /* for messages */
2892: }
2893:
2894: /* fclear -- declare the contents of the file invalid */
2895:
2896: fclear()
2897:
2898: /* Keywords: screen-handling the-screen-map clearing terminal-initialization:20 */
2899:
2900: {
2901: register int i;
2902: scrmap[MODLN] = 0; /* wipe out mode line */
2903: for (i = 0; i < NSCRLIN; i++) fmap[i] = 0;
2904: }
2905:
2906: /* dclear-- cause screen to be cleared at next refresh */
2907:
2908: dclear()
2909: {
2910: /* Keywords: screen-handling clearing break-handling:20 */
2911: junked++;
2912: minln=0;
2913: }
2914:
2915: /* xclear -- declare the contents of the screen as junk */
2916:
2917:
2918: xclear()
2919: {
2920: /* Keywords: screen-handling the-screen-map clearing terminal-initialization:20 */
2921: register int i;
2922:
2923: for(i = 0; i < SCRNLIN; i++) scrmap[i]=0;
2924: }
2925:
2926: /* two window mode -- enter two window mode, prompt user for buffer */
2927:
2928: twind()
2929: {
2930: /* Keywords: windows commands screen-handling:20 */
2931:
2932: if (twowind) return;
2933: twowind = 1;
2934: wscrlines = SCRLINES; /* remember real size */
2935: w1base = (wscrlines/2)-woff; /* Compute start of window 2 */
2936: cwind = 0;
2937: owind(); /* enter second window */
2938: cpbuf(1); /* and go to buffer */
2939: }
2940:
2941: onewind()
2942: {
2943: /* Keywords: windows commands screen-handling:20 */
2944:
2945: if (twowind) {
2946: fclear(); /* file map bad */
2947: twowind = 0;
2948: cwind = 0; /* in window 0 */
2949: wbase = 0;
2950: SCRLINES = wscrlines;
2951: }
2952: }
2953:
2954: /* Return buffer in other window or -1 */
2955:
2956: windbuf()
2957:
2958: /* Keywords: windows commands buffers killing: */
2959: {
2960: if (twind) return(windb[1-cwind]);
2961: else return(-1);
2962: }
2963: owind() /* switch windows */
2964: /* returns -1 if not in two window mode, 0 if different buffer,
2965: and 1 if same buffer */
2966: /* Keywords: windows commands screen-handling:20 */
2967: {
2968: if (!twowind) return(-1);
2969: fclear();
2970: windb[cwind] = curbf;
2971: wminln[cwind] = minln;
2972: wmaxln[cwind] = maxln;
2973:
2974: switch(cwind) {
2975:
2976: case 0:
2977: cwind = 1;
2978: wbase = w1base;
2979: SCRLINES = wscrlines;
2980: break;
2981: case 1:
2982: cwind = 0;
2983: wbase = 0;
2984: SCRLINES=w1base-1;
2985: break;
2986: }
2987:
2988: minln = wminln[cwind];
2989: maxln = wmaxln[cwind];
2990: lastln = SCRLINES-1; /* This is not accurate, but shouldn't matter much */
2991: chbuf(windb[cwind]);
2992: if (windb[0]==windb[1]) return(1);
2993: return(0) ;
2994: }
2995:
2996: wgrow(arg)
2997: register int arg;
2998: /* Keywords: windows screen-lines commands insertion:50 screen-handling:20 */
2999: {
3000: fclear(); /* file map bad */
3001: if (twowind) {
3002: if (cwind) w1base -= arg;
3003: else w1base += arg;
3004: if (w1base < 2) w1base = 2;
3005: if (w1base > wscrlines-1) w1base = wscrlines-1;
3006: woff = (wscrlines/2)-w1base;
3007: if (cwind) {
3008: wbase = w1base;
3009: } else {
3010: SCRLINES = w1base-1;
3011: }
3012: } else {
3013: arg += SCRLINES;
3014: if ((arg > 0) && (arg < MODLN)) SCRLINES = arg;
3015: }
3016: }
3017:
3018: /* Mousing Specials */
3019:
3020: /* Goto screen position at line x, collumn y. arg is decoded as:
3021: * x = arg mod 128.
3022: * y = arg /128.
3023: (128 is more lines than I can imagine on a screen.)
3024:
3025: * Will switch windows, but fails if x is an illegal position. */
3026:
3027: go_xy(arg)
3028: int arg;
3029: /* Keywords: screen-positioning commands macro-programming:40 */
3030: {
3031: register int x,y,c;
3032: int linpos;
3033:
3034: x = arg&127;
3035: y = ((unsigned) arg) >>7;
3036: if ((x <wbase) || (x>= SCRLINES)) {
3037: if (twowind) {
3038: if ((x >= 0) && (x < wscrlines)) {
3039: owind();
3040: } else return(0); /* Can't mouse out of the display */
3041: } else return(0);
3042: }
3043: linpos = scrmap[x]&SCRMSK;
3044: if (linpos== 0) {
3045: if (PICMODE && (maxln == nlines)) {
3046: linpos = maxln+x-lastln;/* If nothing there, punt to end of file */
3047: move(linpos,0);
3048: } else if (x > lastln) {
3049: linpos = maxln;
3050: } else return(0); /* PUNT */
3051: }
3052:
3053: if (findline(linpos)) mline = nln;
3054: else mline = x;
3055:
3056: column = 0;
3057: mcol = LNOMOD*LNOWID-hcol;
3058: if (y<mcol) y = mcol;
3059: clptr=mkline(linpos);
3060: while ((mline < x) || ((mline == x) && (mcol <= y))) {
3061: c = (clptr[column++]&0377);
3062: if (c == EOL) {
3063: if (PICMODE) {
3064: curln=linpos;
3065: column--;
3066: insertc(y-mcol+1,' ');
3067: }
3068: break;
3069: }
3070: if (c & META) mcol+= metal;
3071: switch(ctype[c& 0177]) {
3072:
3073: case PLAIN:
3074: case UL:
3075: mcol++;
3076: break;
3077: case BACKSP:
3078: if (mcol) mcol--;
3079: break;
3080: case CONTRL:
3081: mcol += 2;
3082: break;
3083: case TAB:
3084: mcol+= TABSTOP-((mcol-(LNOMOD*LNOWID))%TABSTOP);
3085: break;
3086: }
3087: if (mcol>SCRWID) {
3088: mline++;
3089: mcol = mcol-SCRWID;
3090: if (LNOMOD) mcol+= LNOWID;
3091: }
3092: }
3093: move(linpos,column-1);
3094: return(1);
3095: }
3096:
3097: vinit()
3098: /* Keywords: terminal-parameters terminal-initialization character-output */
3099: {
3100: #ifndef PC
3101: #ifdef COMPRESS
3102: DOCOMP=CMPON;
3103: #endif
3104:
3105: #ifdef TERMINFO
3106: if (cur_term == NULL) return; /* Catch if called too soon */
3107: if (enter_ca_mode) {
3108: putpad(enter_ca_mode);
3109: }
3110: if (keypad_xmit) {
3111: putpad(keypad_xmit);
3112: }
3113: #else
3114: if (SCINIT) PUTS(SCINIT);
3115: #endif
3116: #endif
3117: }
3118:
3119: vexit ()
3120: {
3121: /* Keywords: terminal-parameters exit-processing character-output */
3122: #ifndef PC
3123: #ifdef COMPRESS
3124: DOCOMP=0;
3125: #endif
3126: #ifdef TERMINFO
3127: if (exit_ca_mode) {
3128: putpad(exit_ca_mode);
3129: }
3130: if (keypad_local) {
3131: putpad(keypad_local);
3132: }
3133: #else
3134: if (VEXIT) PUTS(VEXIT);
3135: #endif
3136: #endif
3137: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.