/* @(#) showstring.c: 1.1 10/15/83 (1.20 3/6/83) */ #include "curses.ext" /* * Dump the string running from first to last out to the terminal. * Take into account attributes, and attempt to take advantage of * large pieces of white space and text that's already there. * oldline is the old text of the line. * * Variable naming convention: *x means "extension", e.g. a rubber band * that briefly looks ahead; *c means a character version of an otherwise * chtype pointer; old means what was on the screen before this call; * left means the char 1 space to the left. */ _showstring(sline, scol, first, last, oldlp) int sline, scol; chtype *first, *last; struct line *oldlp; { register int hl = 0; /* nontrivial line, highlighted or with holes */ int prevhl=SP->virt_gr, thishl; /* highlight state tty is in */ register chtype *p, *px; /* current char being considered */ register chtype *oldp, *oldpx; /* stuff under p and px */ register char *pc, *pcx; /* like p, px but in char buffer */ chtype *tailoldp; /* last valid oldp */ int oldlen; /* length of old line */ int lcol, lrow; /* position on screen */ int oldc; /* char at oldp */ int leftoldc, leftnewc; /* old & new chars to left of p */ int diff_cookies; /* magic cookies changed */ int diff_attrs; /* highlights changed */ chtype *oldline; #ifdef NONSTANDARD static #endif NONSTANDARD char firstc[256], *lastc; /* char copy of input first, last */ #ifdef DEBUG if(outf) fprintf(outf, "_showstring((%d,%d) %d:'", sline, scol, last-first+1); if(outf) for (p=first; p<=last; p++) { thishl = *p & A_ATTRIBUTES; if (thishl) putc('\'', outf); putc(*p & A_CHARTEXT, outf); } if(outf) fprintf(outf, "').\n"); #endif if (last-first > columns) { _pos(lines-1, 0); #ifndef NONSTANDARD fprintf(stderr, "Bad call to _showstring, first %x, last %x,\ diff %d\pcx\n", first, last, last-first); #endif abort(); } if (oldlp) { oldline = oldlp->body; oldp = oldline+scol; } else oldp = 0; for (p=first,lastc=firstc; p<=last; ) { if (*p & A_ATTRIBUTES) hl++; /* attributes on the line */ if (oldp && (*oldp++ & A_ATTRIBUTES)) hl++; /* attributes on old line */ if (*p==' ' && (px=p+1,*px++==' ') && *px++==' ' && *px==' ') hl++; /* a run of at least 4 blanks */ *lastc++ = *p & A_CHARTEXT; p++; /* On a separate line due to C optimizer bug */ #ifdef FULLDEBUG if(outf) fprintf(outf, "p %x '%c' %o, lastc %x %o, oldp %x %o, hl %d\n", p, p[-1], p[-1], lastc, lastc[-1], oldp, oldp ? oldp[-1] : 0, hl); #endif } lastc--; lcol = scol; lrow = sline; if (oldlp) { oldline = oldlp->body; oldlen = oldlp->length; /* Check for runs of stuff that's already there. */ for (p=first,oldp=oldline+lcol; p<=last; p++,oldp++) { if (*p==*oldp && (px=p+1,oldpx=oldp+1,*px++==*oldpx++) && *px++==*oldpx++ && *px==*oldpx) hl++; /* a run of at least 4 matches */ #ifdef FULLDEBUG if(outf) fprintf(outf, "p %x '%c%c%c%c', oldp %x '%c%c%c%c', hl %d\n", p, p[0], p[1], p[2], p[3], oldp, oldp[0], oldp[1], oldp[2], oldp[3], hl); #endif } } else { oldline = NULL; oldlen = 0; } if (!hl) { /* Simple, common case. Do it fast. */ _pos(lrow, lcol); _hlmode(0); _writechars(firstc, lastc); return; } #ifdef DEBUG if(outf) fprintf(outf, "oldlp %x, oldline %x, oldlen %d 0x%x\n", oldlp, oldline, oldlen, oldlen); if(outf) fprintf(outf, "old body('"); if (oldlp) for (p=oldline; p<=oldline+oldlen; p++) if(outf) fprintf(outf, "%c", *p); if(outf) fprintf(outf, "').\n"); #endif oldc = first[-1]; tailoldp = oldline + oldlen; for (p=first, oldp=oldline+lcol, pc=firstc; pc<=lastc; p++,oldp++,pc++) { thishl = *p & A_ATTRIBUTES; #ifdef DEBUG if(outf) fprintf(outf, "prevhl %o, thishl %o\n", prevhl, thishl); #endif leftoldc = oldc & A_ATTRIBUTES; leftnewc = p[-1] & A_ATTRIBUTES; diff_cookies = magic_cookie_glitch>=0 && (leftoldc != leftnewc); diff_attrs = ceol_standout_glitch>=0 && (((*p)&A_ATTRIBUTES) != leftnewc); if (oldp >= tailoldp) oldc = ' '; else oldc = *oldp; #ifdef DEBUG if(outf) fprintf(outf, "p %x *p %o, pc %x *pc %o, oldp %x, *oldp %o, lcol %d, lrow %d, oldc %o\n", p, *p, pc, *pc, oldp, *oldp, lcol, lrow, oldc); #endif if (*p != oldc || SP->virt_irm == 1 || diff_cookies || diff_attrs || insert_null_glitch && oldp >= oldline+oldlen) { register int n; _pos(lrow, lcol); /* * HP 2645/2626: output new for each char. * This forces it to be right no matter what * was there before. */ if (ceol_standout_glitch && thishl == 0 && oldc&A_ATTRIBUTES) { #ifdef FULLDEBUG if(outf) fprintf(outf, "ceol %d, thishl %d, prevhl %d\n", ceol_standout_glitch, thishl, prevhl); #endif _forcehl(); } /* Force highlighting to be right */ _hlmode(thishl); if (thishl != prevhl) { if (magic_cookie_glitch >= 0) { _sethl(); p += magic_cookie_glitch; oldp += magic_cookie_glitch; pc += magic_cookie_glitch; lcol += magic_cookie_glitch; } } /* * Gather chunks of chars together, to be more * efficient, and to allow repeats to be detected. * Not done for blanks on cookie terminals because * the last one might be a cookie. */ if (magic_cookie_glitch<0 || *pc != ' ') { for (px=p+1,oldpx=oldp+1; px<=last && *p==*px; px++,oldpx++) { if(!(repeat_char && oldpx<tailoldp && *p==*oldpx)) break; } px--; oldpx--; n = px - p; pcx = pc + n; } else { n = 0; pcx = pc; } _writechars(pc, pcx); lcol += n; pc += n; p += n; oldp += n; prevhl = thishl; } lcol++; } if (magic_cookie_glitch >= 0 && prevhl) { /* Have to turn off highlighting at end of line */ _hlmode(0); _sethl(); } }