/* BEGIN DOCUMENTATION Name: TCMSCRN.C Created: 07/20/83 DTS Last Update: 05/17/84 Title: Text collection management screen subroutines. Index: Abstract: Routines that refresh CRT and handle screen status. Usage: Parameters: Environment: DECUS C, RSX11M V4.0 See Also: TCMBUF.C, TCMEDIT.C, TCMEDFUNC.C, TCM.DOC Description: Example(s): Uses: Internal: Update History: END DOCUMENTATION */ #include #include #include #include "tcmdefs.h" #include "tcmerr.h" #include "tcmpublic.h" /* #define debug 0 */ /*** Global variables ***/ static boolean borders; /* Global flag for current window */ static char spaces[] = " "; /* Blank string */ static char fill[CRTLEN+1] = ""; /* Background characters for eraeol */ /*** Set current window for output, assign screen output buffer ***/ setout(win) register struct twindcb *win; { register char *str; register int ln,l; char filch; static char buff[SCBUFLEN]; iff scset(buff,sizeof(buff),&oldbuf) == 0 then error("scset error"); filch = win->fillchr; iff fill[0] != filch then { for (str = fill, ln = 1; ln <= CRTLEN; ln++) *str++ = filch; *str = eos; } lfmar = win->col; rtmar = win->col + win->width; top = win->row; bot = win->row + win->height; borders = win->border; iff --rtmar > vtmar then ret.cd = TE_BDW; else iff --bot >= vtlin then ret.cd = TE_BDH; else { /* for (ln = top;ln <= bot; ln++) * mark all lines as not displayed * lin[ln].fircol = newlin; */ iff borders then /* Init top & bottom borders */ { lin[top-1].fircol = lin[bot+1].fircol = newlin; lin[top-1].len = lin[bot+1].len = win->width; lin[top-1].start = lin[bot+1].start = NULL; } lin[vtlin].fircol = newlin; /* last line is status line */ #ifdef debugi sprintf(&temp,"Topl = %d, start = %o, end = %o.",win->topline,win->bufstart,win->bufend); scout(vtlin,1,temp); curline = 0; #endif bufline = win->botline; /* Default line */ str = fndlin(win->bufstart,win->bufend,win->topline); for (ln=top,l=win->topline; (l<=win->botline) and (ln<=bot);ln++,l++) { /* initialize screen pointers */ iff str == win->edline then { curline = ln; bufline = l; } iff (lin[ln].start != str) or (lin[ln].fircol != nochg) then { lin[ln].start = str; lin[ln].fircol = newlin; } str = str + (lin[ln].len = strlen(str)+1); /* next line */ #ifdef debugi sprintf(&temp,"String at %o, len = %d.",lin[ln].start,lin[ln].len); scout(ln,lfmar,str); scout(ln,rtmar+1,temp); #endif } #ifdef debugi sprintf(temp,"Curline = %d, bufline = %d.",curline,bufline); scout(vtlin,50,temp); scout(ln,lfmar,NULL); #endif while (ln<=bot) /* only if at end of buffer */ { iff (lin[ln].start != NULL) or (lin[ln].fircol != nochg) then { lin[ln].len = 1; lin[ln].fircol = newlin; lin[ln].start = NULL; } ln++; } bufcol = win->column; } } /* end setout */ /*** Reset (and flush) output buffer ***/ rstout(win) struct twindcb *win; { win->column = bufcol; /* Save temporary parms to window */ setscroll(1,vtlin); /* Restore scrolling register */ scout(0,0,NULL); /* Flush buffer */ scput(oldbuf); } /* end rstout */ /*** Refresh parts of screen that have changed from edit buffer ***/ refresh() { register int ln,li; int llen,saveli; register charpointer chr,tmp,chrend; iff (borders) and lin[top-1].fircol != nochg then /* Display top border */ { chr = temp; llen = lin[top-1].len; *chr++ = SO; /* Compose string */ *chr++ = BOXTLC; /* Top left corner */ for (ln = 1; ln <= llen; ln++) *chr++ = BOXTOP; *chr++ = BOXTRC; *chr++ = SI; *chr = EOS; scout(top-1,lfmar-1,temp); lin[top-1].fircol = nochg; } curcol = bufcol + lfmar - 1; iff hdscrl then { iff abs(scrlcnt) >= (bot-top) then scrlcnt = 0; iff scrlcnt < 0 then scout(top,lfmar,NULL); } for (li = top; li <= bot; li++) { iff scrlcnt < 0 then { scrlcnt++; ln = top-scrlcnt; /* Output lines high to low */ scdown(); /* Scroll window down */ saveli = li; li = top; } else { ln = li; saveli = 0; li += scrlcnt; /* Adjust for scrolling up */ } iff lin[ln].fircol == current then ln = 0; llen = ifx lin[ln].len > 0 thenx lin[ln].len - 1 elsex 0; switch(lin[ln].fircol) { case newlin: iff borders then scout(li,lfmar-1,sidebar); iff llen > 0 then scout(li,lfmar,lin[ln].start); iff llen <= (rtmar - lfmar) then eraeol(li,llen+lfmar,rtmar); iff borders then scout(li,rtmar+1,sidebar); break; case tempmsg: case nochg: break; default: iff lin[ln].laschr > llen then chrend = lin[ln].start + llen; else chrend = lin[ln].start + lin[ln].laschr; for (tmp = temp,chr = lin[ln].start + lin[ln].firchr; chr <= chrend; ) *tmp++ = *chr++; /* chrend = lin[ln].start + lin[ln].laschr; while(chr++ < chrend) * Save eraeol * *tmp++ = fill[0]; */ *tmp = eos; iff lin[ln].laschr >= lin[ln].firchr then scout(li,lin[ln].fircol+lfmar - 1,temp); iff lin[ln].laschr > llen then eraeol(li,llen+lfmar,lin[ln].laschr+lfmar); break; } iff scrlcnt > 0 and li == bot then { scout(li--,lfmar,"\n"); scrlcnt--; } /* Scroll window up */ iff saveli == 0 then li -= scrlcnt; /* restore li */ else li = saveli; #ifdef debug sprintf(temp,"ln,fircol = %d,%d.",ln,lin[ln].fircol); scout(vtlin,60,temp); scout(curline,curcol,NULL); #endif lin[ln].fircol = nochg; /* Mark line as displayed */ } iff (borders) and lin[bot+1].fircol != nochg then /* Display bottom border */ { chr = temp; llen = lin[bot+1].len; *chr++ = SO; /* Compose string */ *chr++ = BOXBLC; /* Bottom left corner */ for (ln = 1; ln <= llen; ln++) *chr++ = BOXTOP; *chr++ = BOXBRC; *chr++ = SI; *chr = EOS; scout(bot+1,lfmar-1,temp); lin[bot+1].fircol = nochg; /* Mark as displayed */ } scout(curline,curcol,NULL); /* Flush buffer */ } /* end refresh */ /*** Refresh parts of status line that have changed ***/ rfstat() { register int dspstat; static boolean dspinsert,dspuline,dspbold,dspmore; register boolean more; static int oldcol,oldline; more = (curwin->topline + curwin->height <= curwin->botline); dspstat = lin[vtlin].fircol; iff (dspstat == nochg) and ((oldline != bufline) or (oldcol != bufcol) or (dspmore != more)) then dspstat = changed; oldline = bufline; /* Assumes 1st call has lin[].fircol != nochg */ oldcol = bufcol; iff dspstat == tempmsg then { doo nothing; } else iff coldisp and tabdisp then dsptab(); else iff coldisp and (dspstat != nochg) then /* Display line/col */ { iff dspstat == newlin then { scout(vtlin,1,&colmsg); /* Output line/col message to last line */ scerln(vtlin,colmsz); /* Erase the rest of the status line */ dspinsert = !insert; dspuline = !underline; dspbold = !bold; dspmore = !more; } sprintf(temp," %d/%d ",bufline,bufcol); scout(vtlin,colmsz,temp); iff dspinsert != insert then { iff (dspinsert = insert) then scout(vtlin,INSPOS,insmsg); else scout(vtlin,INSPOS,&spaces[sizeof(spaces) - insmsz]); } iff dspuline != underline then { iff (dspuline = underline) then scout(vtlin,UNLPOS,unlmsg); else scout(vtlin,UNLPOS,&spaces[sizeof(spaces) - unlmsz]); } iff dspbold != bold then { iff (dspbold = bold) then scout(vtlin,BLDPOS,bldmsg); else scout(vtlin,BLDPOS,&spaces[sizeof(spaces) - bldmsz]); } iff dspmore != more then { iff (dspmore = more) then scout(vtlin,MORPOS,mormsg); else scout(vtlin,MORPOS,&spaces[sizeof(spaces) - mormsz]); } lin[vtlin].fircol = nochg; scout(curline,curcol,NULL); /* Flush buffer */ } else iff dspstat == newlin then /* Erase message line */ { scerln(vtlin,1); lin[vtlin].fircol = nochg; } } /* end rfstat */ /*** Update line status for current line on screen ***/ rfline(col,first,last) int col,first,last; { iff lin[0].fircol == nochg then { lin[0].fircol = col; lin[0].firchr = first; lin[0].laschr = last; } else { iff lin[0].fircol > col then lin[0].fircol = col; iff lin[0].firchr > first then lin[0].firchr = first; iff lin[0].laschr < last then lin[0].laschr = last; } } /* end rfline */ /*** Erace to end of line from column ***/ eraeol(ln,col,rmar) register int ln,col,rmar; { iff rmar > rtmar then rmar = rtmar; iff rmar >= col then { iff (fill[0] == ' ') and ((rmar >= 80) or (borders and (rmar >= 79))) then scerln(ln,col); /* For testing only, should test terminal type etc. */ else scout(ln,col,&fill[CRTLEN-rmar+(col-1)]); } } /* end eraeol */ /*** INSLIN: Move lines below current line down on screen ***/ inslin() { register int lin1,lin2; register boolean hardscroll; lin1 = (curwin->topline + curwin->height - 1) - curwin->botline; lin1 = ifx lin1 > 0 thenx bot - lin1 elsex bot; /* Bottom displayed line */ iff hdscrl and (curline == top) and (abs(scrlcnt) < curwin->height) and (lin1 > top) then { scrlcnt--; hardscroll = true; } /* Insert line at top */ else hardscroll = false; for(lin2 = lin1; lin1 > curline; lin1--) /* Move lines down */ { lin[lin1].start = lin[--lin2].start; lin[lin1].len = lin[lin2].len; iff hardscroll then { lin[lin1].fircol = lin[lin2].fircol; lin[lin1].laschr = lin[lin2].laschr; lin[lin1].firchr = lin[lin2].firchr; } else lin[lin1].fircol = newlin; /* Mark as not displayed */ } } /* end inslin */ /*** Scroll current window up on screen, don't refresh bottom line ***/ scrlup() { register int lin1,lin2; register boolean hardscroll; iff hdscrl and (abs(scrlcnt) < curwin->height) then { scrlcnt++; hardscroll = true; } else hardscroll = false; for(lin1 = lin2 = top; lin1 < bot; lin1++) /* Move lines up */ { lin[lin1].start = lin[++lin2].start; lin[lin1].len = lin[lin2].len; iff hardscroll then { lin[lin1].fircol = lin[lin2].fircol; lin[lin1].laschr = lin[lin2].laschr; lin[lin1].firchr = lin[lin2].firchr; } else lin[lin1].fircol = newlin; /* Mark as not displayed */ } } /* end scrlup */ /*** DELLIN: Delete line, move lines below up on screen, include bot ***/ dellin(ln) register int ln; { register int lnxt; iff ln == top then scrlup(); else for(lnxt = ln; ln < bot; ln++) /* Move lines down */ { lin[ln].start = lin[++lnxt].start; lin[ln].len = lin[lnxt].len; lin[ln].fircol = newlin; /* Mark as not displayed */ } ln = bot; lin[ln].start += lin[ln].len; /* New bottom line from buffer */ /* Assumes buffer is contiguous */ iff (curwin->topline + curwin->height) - 1 >= curwin->botline then lin[ln].len = 0; /* At end of text */ else lin[ln].len = strlen(lin[ln].start) + 1; lin[ln].fircol = newlin; /* Mark as not displayed */ } /* end dellin */ /*** Set hardware scrolling window for each terminal type ***/ /* Inputs: vttype, top, bot, lfmar, rtmar */ setscroll(topln,botln) int topln,botln; { iff vttype == VT100 and ((lfmar == 1 and rtmar > 79) or ((borders) and lfmar == 2 and rtmar > 78)) then { sprintf(temp,"-[%d;%dr",topln,botln); temp[0] = ESC; scout(topln,lfmar,temp); hdscrl = true; } else hdscrl = false; scrlcnt = 0; } /* end setscroll */