|
|
1.1 root 1: /*********************************************************************
2: * COPYRIGHT NOTICE *
3: **********************************************************************
4: * This software is copyright (C) 1982 by Pavel Curtis *
5: * *
6: * Permission is granted to reproduce and distribute *
7: * this file by any means so long as no fee is charged *
8: * above a nominal handling fee and so long as this *
9: * notice is always included in the copies. *
10: * *
11: * Other rights are reserved except as explicitly granted *
12: * by written permission of the author. *
13: * Pavel Curtis *
14: * Computer Science Dept. *
15: * 405 Upson Hall *
16: * Cornell University *
17: * Ithaca, NY 14853 *
18: * *
19: * Ph- (607) 256-4934 *
20: * *
21: * Pavel.Cornell@Udel-Relay (ARPAnet) *
22: * decvax!cornell!pavel (UUCPnet) *
23: *********************************************************************/
24:
25: /*
26: * lib_doupdate.c
27: *
28: * The routine doupdate() and its dependents
29: *
30: * $Log: lib_doupd.c,v $
31: * Revision 1.1 92/08/31 08:55:43 bin
32: * Initial revision
33: *
34: * Revision 3.2 91/04/20 18:20:16 munk
35: * Usage of register variables
36: *
37: * Revision 3.1 84/12/13 11:20:28 john
38: * Revisions by Mark Horton
39: *
40: * Revision 2.1 82/10/25 14:47:05 pavel
41: * Added Copyright Notice
42: *
43: * Revision 2.0 82/10/25 13:44:33 pavel
44: * Beta-one Test Release
45: *
46: *
47: */
48: #ifndef COHERENT
49: static char RCSid[] =
50: "$Header: /src386/usr/lib/ncurses/RCS/lib_doupd.c,v 1.1 92/08/31 08:55:43 bin Exp Locker: bin $";
51: #endif
52:
53: #include <signal.h>
54: #include "curses.h"
55: #include "curses.priv.h"
56: #include "term.h"
57:
58: #define GoTo(row,col) mvcur(SP->_cursrow, SP->_curscol, row, col); \
59: SP->_cursrow = row; \
60: SP->_curscol = col;
61:
62: #define PutAttrChar(ch) if (curscr->_attrs != (ch & A_ATTRIBUTES)) \
63: { \
64: curscr->_attrs = ch & A_ATTRIBUTES; \
65: vidputs(curscr->_attrs, outc); \
66: } \
67: putc(ch & A_CHARTEXT, SP->_ofp);
68:
69: #define PutChar(ch) if (!auto_right_margin || \
70: SP->_cursrow != lines - 1 || \
71: SP->_curscol != columns - 1) \
72: { \
73: PutAttrChar(ch); \
74: SP->_curscol++; \
75: if (SP->_curscol >= columns) \
76: if (auto_right_margin) \
77: { \
78: SP->_curscol = 0; \
79: SP->_cursrow++; \
80: } \
81: else \
82: SP->_curscol--; \
83: }
84:
85:
86:
87: outc(ch)
88: char ch;
89: {
90: putc(ch, SP->_ofp);
91: }
92:
93:
94: doupdate()
95: {
96: register int i;
97: int (*oldsig)();
98:
99: #ifdef TRACE
100: if (_tracing)
101: _tracef("doupdate() called");
102: #endif
103:
104: #ifdef COHERENT
105: oldsig = signal(SIGTRAP, SIG_IGN);
106: #else
107: oldsig = signal(SIGTSTP, SIG_IGN);
108: #endif
109:
110: if (curscr->_clear)
111: {
112: ClrUpdate(curscr);
113: curscr->_clear = FALSE;
114:
115: GoTo(curscr->_cury, curscr->_curx);
116: }
117: else
118: {
119: if (newscr->_clear)
120: {
121: ClrUpdate(newscr);
122: newscr->_clear = FALSE;
123: }
124: else if (curscr->_idlok)
125: IdlUpdate();
126: else
127: NoIdlUpdate();
128:
129: for (i = 0; i < lines; i++)
130: {
131: newscr->_firstchar[i] = _NOCHANGE;
132: newscr->_lastchar[i] = _NOCHANGE;
133: newscr->_numchngd[i] = 0;
134: }
135:
136: curscr->_curx = newscr->_curx;
137: curscr->_cury = newscr->_cury;
138:
139: GoTo(curscr->_cury, curscr->_curx);
140: }
141:
142:
143: fflush(SP->_ofp);
144:
145: #ifdef COHERENT
146: signal(SIGTRAP, oldsig);
147: #else
148: signal(SIGTSTP, oldsig);
149: #endif
150: }
151:
152:
153: /*
154: ** ClrUpdate(scr)
155: **
156: ** Update by clearing and redrawing the entire screen.
157: **
158: */
159: static
160: ClrUpdate(scr)
161: register WINDOW *scr;
162: {
163: register int i, j;
164:
165: ClearScreen();
166:
167: for (i=0; i < lines; i++)
168: {
169: int lastNonBlank, lastCol;
170:
171: for (lastNonBlank = columns - 1;
172: lastNonBlank && scr->_line[i][lastNonBlank] == ' ';
173: lastNonBlank--)
174: ;
175:
176: if (!lastNonBlank)
177: continue;
178:
179: lastCol = lastNonBlank == (columns - 1);
180: if (lastCol && i == lines)
181: lastNonBlank--;
182:
183: for (j = 0; j <= lastNonBlank; j++) {
184: if (' ' != scr->_line[i][j]) {
185: GoTo(i, j);
186: break;
187: }
188: }
189:
190: for (;j <= lastNonBlank; j++) {
191: PutAttrChar(scr->_line[i][j]);
192: }
193:
194: if (auto_right_margin && lastCol) {
195: SP->_cursrow = i + 1;
196: SP->_curscol = 0;
197: }
198: else
199: SP->_curscol = j;
200: }
201:
202: if (scr != curscr)
203: for (i = 0; i < LINES; i++)
204: for (j = 0; j < COLS; j++)
205: curscr->_line[i][j] = scr->_line[i][j];
206: }
207:
208:
209: /*
210: ** NoIdlUpdate()
211: **
212: ** Update screen without using Insert/Delete Line capabilities
213: **
214: */
215: static
216: NoIdlUpdate()
217: {
218: register int i;
219:
220: #ifdef TRACE
221: if (_tracing)
222: _tracef("NoIdlUpdate() called");
223: #endif
224:
225: for (i=0; i < lines; i++)
226: if (newscr->_numchngd[i])
227: TransformLine(i);
228: }
229:
230:
231:
232: /*
233: ** IdlUpdate()
234: **
235: ** Update screen using Insert/Delete Line capabilities
236: **
237: */
238: #define UNCHANGED(n) (newscr->_numchngd[n] <= columns/10 \
239: || newscr->_lastchar[n] \
240: - newscr->_firstchar[n] <= columns/10)
241:
242: static
243: IdlUpdate()
244: {
245: int firstLine, lastLine;
246: register int thisLine;
247:
248: #ifdef TRACE
249: if (_tracing)
250: _tracef("IdlUpdate() called");
251: #endif
252:
253: firstLine = -1;
254:
255: for (thisLine = 0; thisLine < lines; thisLine++)
256: {
257: if (UNCHANGED(thisLine))
258: {
259: if (firstLine != -1)
260: {
261: lastLine = thisLine - 1;
262: Gosling(firstLine, lastLine);
263: firstLine = -1;
264: }
265:
266: if (newscr->_firstchar[thisLine] != _NOCHANGE)
267: TransformLine(thisLine);
268: }
269: else if (firstLine == -1)
270: firstLine = thisLine;
271: }
272:
273: if (firstLine != -1)
274: Gosling(firstLine, lines - 1);
275: }
276:
277:
278: /*
279: ** TransformLine(lineno)
280: **
281: ** Call either IDcTransformLine or NoIDcTransformLine to do the
282: ** update, depending upon availability of insert/delete character.
283: */
284: static
285: TransformLine(lineno)
286: int lineno;
287: {
288: if ( (insert_character || (enter_insert_mode && exit_insert_mode))
289: && delete_character)
290: IDcTransformLine(lineno);
291: else
292: NoIDcTransformLine(lineno);
293: }
294:
295:
296: /*
297: ** NoIDcTransformLine(lineno)
298: **
299: ** Transform the given line in curscr to the one in newscr, without
300: ** using Insert/Delete Character.
301: **
302: ** firstChar = position of first different character in line
303: ** lastChar = position of last different character in line
304: **
305: ** overwrite all characters between firstChar and lastChar.
306: **
307: */
308: static
309: NoIDcTransformLine(lineno)
310: int lineno;
311: {
312: register int firstChar, lastChar;
313: register chtype *newLine = newscr->_line[lineno];
314: register chtype *oldLine = curscr->_line[lineno];
315: register int k;
316:
317: #ifdef TRACE
318: if (_tracing)
319: _tracef("NoIDcTransformLine(%d) called", lineno);
320: #endif
321:
322: firstChar = 0;
323: while (firstChar < columns
324: && newLine[firstChar] == oldLine[firstChar])
325: firstChar++;
326:
327: if (firstChar >= columns)
328: return;
329:
330: lastChar = columns - 1;
331: while (lastChar > firstChar && newLine[lastChar] == oldLine[lastChar])
332: lastChar--;
333:
334: GoTo(lineno, firstChar);
335:
336: for (k=firstChar; k <= lastChar; k++)
337: {
338: PutChar(newLine[k]);
339: oldLine[k] = newLine[k];
340: }
341: }
342:
343:
344: /*
345: ** IDcTransformLine(lineno)
346: **
347: ** Transform the given line in curscr to the one in newscr, using
348: ** Insert/Delete Character.
349: **
350: ** firstChar = position of first different character in line
351: ** oLastChar = position of last different character in old line
352: ** nLastChar = position of last different character in new line
353: **
354: ** move to firstChar
355: ** overwrite chars up to min(oLastChar, nLastChar)
356: ** if oLastChar < nLastChar
357: ** insert newLine[oLastChar+1..nLastChar]
358: ** else
359: ** delete oLastChar - nLastChar spaces
360: */
361: static
362: IDcTransformLine(lineno)
363: int lineno;
364: {
365: int firstChar, oLastChar, nLastChar;
366: chtype *newLine = newscr->_line[lineno];
367: chtype *oldLine = curscr->_line[lineno];
368: register int k, n;
369:
370: #ifdef TRACE
371: if (_tracing)
372: _tracef("IDcTransformLine(%d) called", lineno);
373: #endif
374:
375: firstChar = 0;
376: while (firstChar < columns && newLine[firstChar] == oldLine[firstChar])
377: firstChar++;
378:
379: if (firstChar >= columns)
380: return;
381:
382: oLastChar = columns - 1;
383: while (oLastChar > firstChar && oldLine[oLastChar] == ' ')
384: oLastChar--;
385:
386: nLastChar = columns - 1;
387: while (nLastChar > firstChar && newLine[nLastChar] == ' ')
388: nLastChar--;
389:
390: while (newLine[nLastChar] == oldLine[oLastChar])
391: {
392: nLastChar--;
393: oLastChar--;
394: }
395:
396: n = min(oLastChar, nLastChar);
397: GoTo(lineno, firstChar);
398:
399: for (k=firstChar; k <= n; k++)
400: PutChar(newLine[k]);
401:
402: if (oLastChar < nLastChar)
403: InsStr(&newLine[k], nLastChar - oLastChar);
404: else if (oLastChar > nLastChar)
405: DelChar(oLastChar - nLastChar);
406:
407: for (k=firstChar; k < columns; k++)
408: oldLine[k] = newLine[k];
409: }
410:
411:
412: /*
413: ** Gosling(firstLine, lastLine)
414: **
415: ** Change the given range of lines on curscr into the same lines
416: ** on newscr, using Gosling's Algorithm.
417: */
418: static short lineCost[MAXLINES][MAXLINES];
419: static short lineOps[MAXLINES][MAXLINES];
420: static short lineDels[MAXLINES];
421: static short lineIRs[MAXLINES];
422:
423: #define INSERT 1
424: #define DELETE 2
425: #define REPLACE 3
426:
427: static
428: Gosling(firstLine, lastLine)
429: int firstLine, lastLine;
430: {
431: register int i, count;
432:
433: #ifdef TRACE
434: if (_tracing)
435: _tracef("Gosling(%d,%d) called", firstLine, lastLine);
436: #endif
437:
438: Goscost(firstLine, lastLine - firstLine + 1);
439:
440: for (i=0; i <= lastLine - firstLine + 1; i++)
441: lineDels[i] = lineIRs[i] = 0;
442:
443: Gosdraw(lastLine - firstLine + 1, lastLine - firstLine + 1);
444:
445: count = 0;
446: for (i = lastLine - firstLine + 1; i > 0; i--)
447: {
448: if (lineDels[i] == DELETE)
449: count++;
450: else if (count)
451: {
452: DelLine(count, firstLine + i, lastLine);
453: count = 0;
454: }
455: }
456:
457: if (count)
458: DelLine(count, firstLine, lastLine);
459:
460:
461: for (i = 1; i <= lastLine - firstLine + 1; i++)
462: {
463: switch (lineIRs[i])
464: {
465: case REPLACE:
466: TransformLine(firstLine + i - 1);
467: break;
468:
469: case INSERT:
470: InsLine(firstLine + i - 1, lastLine);
471: break;
472:
473: default:
474: /* do nothing */
475: break;
476: }
477: }
478: }
479:
480:
481: #define RPLCOST(old,new) (oHash[old] == nHash[new] ? 0 : columns)
482:
483: static
484: Goscost(lineno, length)
485: int lineno, length;
486: {
487: register int i, j;
488: int cost, ILcost, DLcost;
489: long nHash[MAXLINES], oHash[MAXLINES];
490: long HashFn();
491:
492: #ifdef TRACE
493: if (_tracing)
494: _tracef("Goscost(lineno=%d,length=%d) called", lineno, length);
495: #endif
496:
497: ILcost = (insert_line ? strlen(insert_line) : 9999) + columns;
498: DLcost = (delete_line ? strlen(delete_line) : 9999);
499:
500: for (i=1; i <= length; i++)
501: {
502: nHash[i] = HashFn(newscr->_line[lineno + i - 1]);
503: oHash[i] = HashFn(curscr->_line[lineno + i - 1]);
504: }
505:
506: lineCost[0][0] = 0;
507:
508: for (i=1; i <= length; i++)
509: {
510: lineCost[i][0] = lineCost[i-1][0] + DLcost;
511: lineOps[i][0] = DELETE;
512:
513: lineCost[0][i] = lineCost[0][i-1] + ILcost;
514: lineOps[0][i] = INSERT;
515: }
516:
517: for (i=1; i <= length; i++)
518: {
519: for (j=1; j <= length; j++)
520: {
521: lineCost[i][j] = lineCost[i-1][j-1] + RPLCOST(i, j);
522: lineOps[i][j] = REPLACE;
523:
524: cost = lineCost[i][j-1] + ILcost;
525: if (cost < lineCost[i][j])
526: {
527: lineCost[i][j] = cost;
528: lineOps[i][j] = INSERT;
529: }
530:
531: cost = lineCost[i-1][j] + DLcost;
532: if (cost < lineCost[i][j])
533: {
534: lineCost[i][j] = cost;
535: lineOps[i][j] = DELETE;
536: }
537: }
538: }
539:
540: return(lineCost[columns][columns]);
541: }
542:
543:
544: /*
545: ** _PrintCosts(length)
546: **
547: ** Print out the cost matrix. Called only from sdb.
548: **
549: **
550: ** _DumpNewscr(first, last)
551: **
552: ** Print the specified range of lines from newscr. Called only from sdb.
553: **
554: **
555: ** _DumpCurscr(first, last)
556: **
557: ** Print the specified range of lines from curscr. Called only from sdb.
558: **
559: */
560: _PrintCosts(length)
561: int length;
562: {
563: register int i, j;
564:
565: for (i=0; i <= length; i++)
566: {
567: for (j=0; j <= length; j++)
568: {
569: printf("%5d/%d", lineCost[i][j], lineOps[i][j]);
570: }
571:
572: putchar('\n');
573: }
574:
575: fflush(stdout);
576: }
577:
578:
579: _DumpNewscr(first, last)
580: int first, last;
581: {
582: register int i, j;
583:
584: for (i=first; i <= last; i++)
585: {
586: for (j=0; j < columns; j++)
587: putchar(newscr->_line[i][j]);
588:
589: putchar('\n');
590: }
591: }
592:
593:
594: _DumpCurscr(first, last)
595: int first, last;
596: {
597: register int i, j;
598:
599: for (i=first; i <= last; i++)
600: {
601: for (j=0; j < columns; j++)
602: putchar(curscr->_line[i][j]);
603:
604: putchar('\n');
605: }
606: }
607:
608:
609: long
610: HashFn(line)
611: register chtype *line;
612: {
613: register int i = 0;
614: long hash = 0;
615:
616: while(i < columns && (line[i] | A_CHARTEXT) == ' ')
617: i++;
618:
619: for (; i+1 < columns; i += 2)
620: hash += (line[i] << 8) + line[i+1];
621:
622: return (hash);
623: }
624:
625:
626:
627:
628:
629: static
630: Gosdraw(i, j)
631: register int i, j;
632: {
633: if (i == 0 && j == 0)
634: return;
635:
636: switch (lineOps[i][j])
637: {
638: case INSERT:
639: Gosdraw(i, j-1);
640: lineIRs[j] = INSERT;
641: break;
642:
643: case DELETE:
644: lineDels[i] = DELETE;
645: Gosdraw(i-1, j);
646: break;
647:
648: case REPLACE:
649: Gosdraw(i-1, j-1);
650: lineIRs[j] = REPLACE;
651: break;
652: }
653: }
654:
655:
656: /*
657: ** ClearScreen()
658: **
659: ** Clear the physical screen and put cursor at home
660: **
661: */
662: static
663: ClearScreen()
664: {
665: if (clear_screen)
666: {
667: tputs(clear_screen, 1, outc);
668: SP->_cursrow = SP->_curscol = 0;
669: }
670: else if (clr_eos)
671: {
672: SP->_cursrow = SP->_curscol = -1;
673: GoTo(0,0);
674:
675: tputs(clr_eos, 1, outc);
676: }
677: else if (clr_eol)
678: {
679: SP->_cursrow = SP->_curscol = -1;
680:
681: while (SP->_cursrow < lines)
682: {
683: GoTo(SP->_cursrow, 0);
684: tputs(clr_eol, 1, outc);
685: }
686:
687: GoTo(0,0);
688: }
689: }
690:
691:
692: /*
693: ** InsStr(line, count)
694: **
695: ** Insert the count characters pointed to by line.
696: **
697: */
698: InsStr(line, count)
699: register chtype *line;
700: register int count;
701: {
702: #ifdef TRACE
703: if (_tracing)
704: _tracef("InsStr(%o,%d) called", line, count);
705: #endif
706:
707: if (enter_insert_mode && exit_insert_mode)
708: {
709: tputs(enter_insert_mode, 1, outc);
710: while (count)
711: {
712: PutChar(*line);
713: line++;
714: count--;
715: }
716: tputs(exit_insert_mode, 1, outc);
717: }
718: else if (parm_ich)
719: {
720: tputs(tparm(parm_ich, count), 1, outc);
721: while (count)
722: {
723: PutChar(*line);
724: line++;
725: count--;
726: }
727: }
728: else
729: {
730: while (count)
731: {
732: tputs(insert_character, 1, outc);
733: PutChar(*line);
734: line++;
735: count--;
736: }
737: }
738: }
739:
740:
741: /*
742: ** DelChar(count)
743: **
744: ** Delete count characters at current position
745: **
746: */
747: DelChar(count)
748: register int count;
749: {
750: #ifdef TRACE
751: if (_tracing)
752: _tracef("DelChar(%d) called", count);
753: #endif
754:
755: if (parm_dch)
756: {
757: tputs(tparm(parm_dch, count), 1, outc);
758: }
759: else
760: {
761: while (count--)
762: tputs(delete_character, 1, outc);
763: }
764: }
765:
766:
767: /*
768: ** InsLine(lineno, lastLine)
769: **
770: ** Insert line number lineno, affecting up to lastLine
771: **
772: */
773: InsLine(lineno, lastLine)
774: int lineno, lastLine;
775: {
776: register int i, j, k;
777: chtype *temp;
778: chtype *line = newscr->_line[lineno];
779:
780: #ifdef TRACE
781: if (_tracing)
782: _tracef("InsLine(%d,%d) called", lineno, lastLine);
783: #endif
784:
785: GoTo(lineno, 0);
786:
787: tputs(insert_line, 1, outc);
788:
789: for (i=0; i < columns; i++)
790: PutChar(line[i]);
791:
792: temp = curscr->_line[lastLine];
793: for (k = lastLine; k > lineno; k--)
794: curscr->_line[k] = curscr->_line[k - 1];
795:
796: curscr->_line[k] = temp;
797:
798: for (j=0; j < columns; j++)
799: curscr->_line[k][j] = newscr->_line[k][j];
800: }
801:
802:
803: /*
804: ** DelLine(count, lineno, lastLine)
805: **
806: ** Delete count lines at lineno, affecting up to lastLine
807: **
808: */
809: DelLine(count, lineno, lastLine)
810: int count, lineno, lastLine;
811: {
812: register int j, k;
813: chtype *temp;
814:
815: #ifdef TRACE
816: if (_tracing)
817: _tracef("DelLine(%d,%d,%d) called", count, lineno, lastLine);
818: #endif
819:
820: GoTo(lineno, 0);
821:
822: if (parm_delete_line)
823: {
824: tputs(tparm(parm_delete_line, count), 1, outc);
825: }
826: else
827: {
828: while (count--)
829: tputs(delete_line, 1, outc);
830: }
831:
832: for (k = lineno; k + count <= lastLine; k++)
833: {
834: temp = curscr->_line[k];
835: curscr->_line[k] = curscr->_line[k + count];
836: curscr->_line[k + count] = temp;
837: }
838:
839: for (; k <= lastLine; k++)
840: for (j=0; j < columns; j++)
841: curscr->_line[k][j] = ' ';
842: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.