home *** CD-ROM | disk | FTP | other *** search
- #ifdef lint
- static char *SCCSid = "%W% (NCSA) %G%";
- #endif
-
- /*
- *
- * Virtual Screen Kernel Internal Routines
- * (vsintern.c)
- * National Center for Supercomputing Applications
- *
- * by Gaige B. Paulsen
- *
- * This file contains the private internal calls for the NCSA
- * Virtual Screen Kernel.
- *
- * Version Date Notes
- * ------- ------ ---------------------------------------------------
- * 0.01 861102 Initial coding -GBP
- * 0.50 861113 First compiled edition -GBP
- * 0.70 861114 Internal operation confirmed -GBP
- * 2.1 871130 NCSA Telnet 2.1 -GBP
- * 2.2 880715 NCSA Telnet 2.2 -GBP
- */
-
- #include <String.h>
- #include <Quickdraw.h>
- #include <Controls.h>
- #include <Memory.h>
- #include <OSUtils.h> /* BYU 2.4.12 */
- #include "vsdata.h"
- #include "vskeys.h"
- #include "vsinterf.h"
- #include "rsmac.h"
-
- #define ScrollbackQuantum 100
-
- #define VSIclrattrib 0
-
- extern SysEnvRec theWorld; /* BYU 2.4.12 - System Environment record */
- extern int isEightBit(); /* BYU 2.4.12 */
-
- int VSIclip
- (
- int *x1, /* starting column */
- int *y1, /* line on which to draw (assumed to lie within visible region) */
- int *x2, /* ending column (inclusive) (output if *n >= 0) */
- int *y2, /* ending line (inclusive) (output if *n >= 0) */
- int *n, /* length of text to draw (input and output) */
- int *offset /* length of initial part of text to skip (output) */
- )
- /* clips a text string to the visible region, given the starting
- line and column in screen coordinates at which it is to be drawn.
- If the length of the string is given, will also compute the ending
- line and column. On return, these coordinates will be normalized
- to the current visible region. Returns a nonzero function result
- iff the string is completely invisible. */
- {
- if (*n >= 0)
- {
- /* compute ending line and column (inclusive) */
- *x2 = *x1 + *n - 1;
- *y2 = *y1;
- }
- /* else take these as given */
-
- if ((*x1 > VSIw->Rright) || (*y2 < VSIw->Rtop))
- return (-1); /* nothing to draw */
-
- if (*x2 > VSIw->Rright)
- *x2 = VSIw->Rright;
- if (*y2 > VSIw->Rbottom)
- *y2 = VSIw->Rbottom;
- /* normalize x1, x2, y1, y2 to be relative to current visible region */
- *x1 -= VSIw->Rleft;
- *x2 -= VSIw->Rleft;
- *y1 -= VSIw->Rtop;
- *y2 -= VSIw->Rtop;
- /* clip part of text string lying outside region, if any */
- *offset = - *x1;
- if (*offset < 0)
- *offset = 0; /* text string starts within region--nothing to clip */
- /* don't draw anything outside region */
- if (*x1 < 0)
- *x1 = 0;
- if (*y1 < 0)
- *y1 = 0;
-
- *n = *x2 - *x1 + 1 ; /* length of string to draw (assuming it's all on one line) */
- if ((*n <= 0) || (*y2 - *y1 < 0))
- return (-1); /* nothing to draw */
- return (0);
- } /* VSIclip */
-
- VSIcdellines(w, top, bottom, n, scrolled)
- int
- w, /* affected window */
- top, /* where to start deleting from */
- bottom, /* bottom line of region to scroll */
- n, /* number of lines to delete */
- scrolled;
- /*
- -ve => cancel current selection, if any;
- +ve => selection has moved up one line;
- 0 => don't touch selection
- */
- /* updates the display to indicate deletion of the specified
- number of lines from the top of the specified region.
- Returns 0 iff any part of the change is visible. */
- {
- int
- x1 = 0,
- x2 = VSIw->maxwidth,
- tn = -1,
- offset;
-
- if (VSIclip(&x1, &top, &x2, &bottom, &tn, &offset))
- return(-1); /* affected region is invisible */
- tn = bottom - top;
- if (tn < n)
- n = tn; /* don't bother scrolling more lines than scrolling region holds */
- RSdellines(w, top, bottom, n, scrolled);
- return(0); /* I delete the whole thing! */
- } /* VSIcdellines */
-
- VSIcinslines(w, top, bottom, n,scrolled)
- int
- w, /* affected window */
- top, /* where to insert blank lines */
- bottom, /* bottom of area to scroll */
- n, /* number of lines to insert */
- scrolled; /* -ve <=> cancel current selection, if any */
- /* updates the display to indicate insertion of the specified
- number of blank lines at the top of the specified region.
- Returns 0 iff any part of the change is visible. */
- {
- int
- x1 = 0,
- x2 = VSIw->maxwidth,
- tn = -1,
- offset;
-
- if (VSIclip(&x1, &top, &x2, &bottom, &tn, &offset))
- return -1; /* affected region is invisible */
- tn = bottom - top;
- if (tn < n)
- n = tn; /* don't bother scrolling more lines than scrolling region holds */
- RSinslines(w, top, bottom, n, scrolled);
- return 0;
- } /* VSIcinslines */
-
- void VSIcurson
- (
- int w,
- int x,
- int y,
- int ForceMove
- )
- /* displays the text cursor at the specified position. If
- ForceMove is true, I am to do any appropriate scrolling of
- the display to ensure the cursor is within the visible region.
- Assumes cursor isn't currently being shown. */
- {
- int
- x2,
- y2,
- n = 1,
- offset;
-
- if (!VSIclip(&x, &y, &x2, &y2, &n, &offset))
- /* cursor already lies within visible region */
- RScurson(w, x, y); /* just make it visible */
- else if (ForceMove)
- {
- /* scroll to make cursor visible */
- x2 = VSIw->Rbottom - VSIw->Rtop;
- if (x2 >= VSIw->lines)
- /* visible region is big enough to show entire screen--
- make sure I don't scroll off the bottom of the screen.
- This call will also do any appropriate scrolling and
- redisplaying of the cursor. */
- VSsetrgn(VSIwn, VSIw->Rleft, VSIw->lines - x2,
- VSIw->Rright, VSIw->lines);
- else
- {
- /* x & y have been normalized relative to left & top
- of current visible region. Just call the appropriate scroll
- routine, which will also redisplay the cursor. */
- if (y > 0)
- VSscrolforward(VSIwn, y);
- else
- VSscrolback(VSIwn, -y);
- } /* if */
- } /* if */
- } /* VSIcurson */
-
- void VSIcuroff
- (
- int w
- )
- /* hides the cursor for the specified screen. Assumes it
- is currently being shown (or that it's on an invisible
- part of the screen). */
- {
- int
- x = VSIw->x,
- y = VSIw->y,
- x2,
- y2,
- n = 1,
- offset;
-
- if (!VSIclip(&x, &y, &x2, &y2, &n, &offset))
- /* cursor is on visible part of screen */
- RScursoff(w);
- } /* VSIcuroff */
-
- int VSIcursorvisible /* BYU 2.4.12 */
- ( /* BYU 2.4.12 */
- void /* BYU 2.4.12 */
- ) /* BYU 2.4.12 */
- { /* BYU 2.4.12 */
- int /* BYU 2.4.12 */
- x = VSIw->x, /* BYU 2.4.12 */
- y = VSIw->y, /* BYU 2.4.12 */
- x2, /* BYU 2.4.12 */
- y2, /* BYU 2.4.12 */
- n = 1, /* BYU 2.4.12 */
- offset; /* BYU 2.4.12 */
- /* BYU 2.4.12 */
- if (!VSIclip(&x, &y, &x2, &y2, &n, &offset)) /* BYU 2.4.12 */
- return 1; /* BYU 2.4.12 */
- else /* BYU 2.4.12 */
- return 0; /* BYU 2.4.12 */
- } /* BYU 2.4.12 */
-
- VSlineArray VSInewlinearray
- (
- int nrlines
- )
- /* allocates an array to hold the specified number of pointers
- to line elements. */
- {
- return
- (VSlineArray) NewPtr(sizeof(VSlinePtr) * nrlines);
- } /* VSInewlinearray */
-
- VSlinePtr VSInewlines
- (
- int nlines
- )
- /* allocates a doubly-linked list of the specified number of
- line elements, and returns a pointer to the head of the list,
- or nil if ran out of memory. The maximum number of characters
- each line can hold is controlled by VSIw->allwidth. */
- {
- VSlinePtr t2;
- char *t;
- register int i;
-
- if (!RSokmem(30000)) /* don't use up end of mem for scrollback */
- return((VSlinePtr) 0L);
- /* allocate one block for the line list elements, and another
- block for the line contents. These blocks will be divided up
- and appropriate flags set so I will be able to call DisposPtr
- the right number of times, with the right arguments. */
- if ((t = NewPtr(nlines * (VSIw->allwidth + 1))) != 0L)
- {
- if ((t2 = (VSlinePtr) NewPtr(nlines * sizeof(VSline))) != 0L)
- t2->text = t;
- else
- {
- /* clean up gracefully before giving up */
- DisposPtr(t);
- return(0L);
- } /* if */
- }
- else
- /* sorree no memoree */
- return((VSlinePtr) 0L);
-
- /*
- * indicate to the free routine that the first record is the one to free.
- */
- t2->mem = 1; /* call DisposPtr on this one */
- t2->next = t2 + 1; /* point to next one */
- /*
- * Take our allocation for multiple lines and fill in the structures to
- * point to the right text fields and connect the doubly-linked chain.
- *
- */
- for (i = 1; i < nlines; i++)
- {
- t += (VSIw->allwidth + 1); /* inc to next text space for a line */
- t2[i].mem = 0; /* don't DisposPtr any of these */
- t2[i].text = t;
- t2[i].prev = t2 + i - 1; /* point back one */
- t2[i].next = t2 + i + 1; /* point forward one */
- } /* for */
-
- t2[0].prev = 0L; /* first one has no prev yet */
- t2[nlines - 1].next = 0L; /* last one has no next yet */
-
- return(t2);
- } /* VSInewlines */
-
- void VSIlistndx
- (
- register VSlinePtr ts,
- register VSlinePtr as
- )
- /* sets up the screen arrays for the current screen to point
- at the given lists of attribute and text lines. */
- {
- register int i;
- for (i = 0; i <= VSIw->lines; i++)
- {
- VSIw->attrst[i] = as;
- VSIw->linest[i] = ts;
- ts = ts->next;
- as = as->next;
- } /* for */
- } /* VSIlistndx */
-
- void VSIscroff
- (
- void
- )
- /* called to save current screen contents in scrollback buffer,
- if it is ordained that I should do so. This is called by VSIes
- (below) just before the entire screen is cleared. */
- {
- VSlinePtr tmp;
- register int i, j;
-
- if
- (
- (!VSIw->savelines) /* not saving lines */
- ||
- (VSIw->top != 0) || (VSIw->bottom != VSIw->lines)
- /* scrolling region isn't exactly the entire screen */
- )
- return; /* do nothing */
-
- tmp = VSIw->linest[VSIw->lines]; /* need VSIw->lines + 1 more lines */
- for (i = 0; i <= VSIw->lines; i++)
- {
- /* count off the lines in the part of the scrollback buffer
- below the screen (if any), to see if there's enough to hold
- a screenful. If the scrollback list isn't circular, then
- this part contains lines that have been allocated, but not
- yet used. If the list is circular (meaning it has reached
- its full size), then this is the part that is next in line
- for reuse. */
- if (!tmp->next)
- { /* not enough */
- j = VSIw->maxlines - VSIw->numlines - i; /* potential unallocated scrollback */
- if (j > ScrollbackQuantum)
- j = ScrollbackQuantum; /* but don't bother allocating more than this */
- if (j <= 0)
- {
- /* already reached user-specified scrollback limit-- */
- /* make the list circular to indicate no more extension. */
- tmp->next = VSIw->buftop;
- VSIw->buftop->prev = tmp; /* connect it up */
- }
- else
- {
- /* extend the scrollback buffer to make room for
- another screenful */
- if (j < VSIw->lines - i + 1)
- j = VSIw->lines - i + 1; /* need at least this many */
- if ((tmp->next = VSInewlines(j)) != 0L)
- tmp->next->prev = tmp; /* got some space--link it up */
- else
- {
- /* out of memory--no more extensions */
- tmp->next = VSIw->buftop;
- VSIw->buftop->prev = tmp;
- } /* if */
- } /* if */
- break; /* only allocate once is enough */
- } /* if */
- tmp = tmp->next; /* keep counting */
- } /* for */
-
- /*
- * at this point, we know we have enough memory for the whole scroll.
- * It might be wraparound (reuse of some line elements), might not.
- */
-
- for (i = 0; i <= VSIw->lines; i++)
- {
- /* push another screen line into the scrollback area */
- if (VSIw->linest[VSIw->lines]->next == VSIw->buftop)
- VSIw->buftop = VSIw->buftop->next; /* reusing old space */
- else
- VSIw->numlines++; /* using some new space */
- VSIw->scrntop = VSIw->scrntop->next; /* move another line into the scrollback buffer */
- VSIlistndx(VSIw->scrntop, VSIw->attrst[1]); /* and update screen arrays */
- /* note that it's up to the caller to clear out the new screen text
- and attribute lines */
- } /* for */
-
- VSIw->vistop = VSIw->scrntop;
- RSbufinfo(VSIwn, VSIw->numlines, VSIw->Rtop, VSIw->Rbottom); /* update vertical scroll bar */
- } /* VSIscroff */
-
- void VSIelo
- (
- int s /* line to erase, -ve => line containing cursor */
- )
- /* blanks out the specified line in the screen buffer.
- Doesn't do anything to the display. */
- {
- char *tt, *ta;
- int i;
-
- if (s < 0)
- s = VSIw->y;
-
- ta = &VSIw->attrst[s]->text[0];
- tt = &VSIw->linest[s]->text[0];
- for (i = 0; i <= VSIw->allwidth; i++)
- {
- *ta++ = VSIclrattrib;
- *tt++ = ' ';
- } /* for */
- } /* VSIelo */
-
- void VSIes
- (
- void
- )
- /* clears the screen, first saving its contents in the
- scrollback buffer if appropriate. Also updates the display. */
- {
- int
- i;
- int
- x1 = 0,
- y1 = 0,
- x2 = VSIw->maxwidth,
- y2 = VSIw->lines,
- n = -1,
- offset;
-
- /* save screen contents in scrollback buffer, if appropriate */
- if (VSIw->ESscroll)
- VSIscroff();
- /* clear out screen buffer */
- for (i = 0; i <= VSIw->lines; i++)
- VSIelo(i);
- /* update display to show what I've done */
- if (!VSIclip(&x1, &y1, &x2, &y2, &n, &offset))
- RSerase(VSIwn, x1, y1, x2, y2);
- VSIw->vistop = VSIw->scrntop;
- } /* VSIes */
-
- void VSItabclear
- (
- void
- )
- /* clears all current tab settings. */
- {
- int
- x = 0;
-
- while (x <= VSIw->allwidth)
- {
- VSIw->tabs[x] = ' ';
- x++;
- } /* while */
- } /* VSItabclear */
-
- void VSItabinit
- (
- void
- )
- /* sets tab settings to default (every 8 columns). */
- {
- int
- x = 0;
-
- VSItabclear();
- while (x <= VSIw->allwidth)
- {
- VSIw->tabs[x] = 'x';
- x += 8;
- }
- VSIw->tabs[VSIw->allwidth] = 'x';
- } /* VSItabinit */
-
- void VSIreset
- (
- void
- )
- /* restores terminal mode settings to defaults and clears screen. */
- {
- VSIw->top = 0;
- VSIw->bottom = VSIw->lines;
- VSIw->parmptr = 0;
- VSIw->escflg = 0;
- VSIw->DECAWM = 0;
- VSIw->DECCKM = 0;
- VSIw->DECPAM = 0;
- VSIw->DECORG = 0;
- VSIw->IRM = 0;
- VSIw->attrib = 0;
- VSIw->Pattrib = -1;
- VSIw->x = 0;
- VSIw->y = 0;
- VSIw->charset = 0;
- VSIes();
- VSItabinit();
- } /* VSIreset */
-
- VSIlistmove(TD, BD, TI, BI)
- register VSlinePtr TD, BD, TI, BI;
- /* moves the lines from TD to BD inclusive from their
- present position to between TI and BI. Either of the
- latter may be nil. */
- {
- /* unlink the lines from TD to BD */
- if (TD->prev != 0L)
- TD->prev->next = BD->next; /* Maintain circularity */
- if (BD->next != 0L)
- BD->next->prev = TD->prev;
- /* relink them between TI and BI */
- TD->prev = TI; /* Place the node in its new home */
- BD->next = BI;
- if (TI != 0L)
- TI->next = TD; /* Ditto prev->prev */
- if (BI != 0L)
- BI->prev = BD;
- } /* VSIlistmove */
-
- void VSIdellines
- (
- int n, /* nr lines to delete */
- int s /* starting line to delete, -ve => line containing cursor */
- )
- /* deletes lines from the screen, scrolling up the remainder and
- inserting new blank lines at the bottom of the scrolling region. */
- {
- int i, j;
- char *ta, *tt;
- VSlinePtr as, ts, TD, BD, TI, BI, itt, ita;
-
- if (s < 0)
- s = VSIw->y;
- if (s + n - 1 > VSIw->bottom)
- n = VSIw->bottom - s + 1; /* don't bother deleting more than scrolling region will hold */
-
- /* find new tops of screen arrays */
- if (s == 0 && n <= VSIw->lines)
- {
- /* element for line after last one being deleted */
- ts = VSIw->linest[n];
- as = VSIw->attrst[n];
- }
- else
- {
- /* top line unaffected, or entire screen is being wiped */
- ts = VSIw->linest[0];
- as = VSIw->attrst[0];
- } /* if */
-
- TD = VSIw->linest[s]; /* topmost line to delete */
- BD = VSIw->linest[s + n - 1]; /* bottommost line to delete */
- TI = VSIw->linest[VSIw->bottom]; /* insert replacement blank lines after this line */
- BI = TI->next; /* insert them before this line (might be nil) */
- itt = TD; /* start of text lines to be blanked out */
- /* the space taken by the deleted lines will be reused for
- the inserted blank lines */
- if (TD != BI && TI != BD)
- /* insertion and deletion areas not adjacent -- move the lines to
- their new position */
- VSIlistmove(TD, BD, TI, BI);
-
- TD = VSIw->attrst[s]; /* topmost line to delete */
- BD = VSIw->attrst[s + n - 1]; /* bottommost line to delete */
- TI = VSIw->attrst[VSIw->bottom]; /* insert new lines after this one */
- BI = TI->next; /* insert them before this line */
- /* perform same rearrangement on attribute lines as on text lines */
- if (TD != BI && TI != BD)
- /* insertion and deletion areas not adjacent -- move the lines to
- their new position */
- VSIlistmove(TD, BD, TI, BI);
-
- /* blank out the newly-created replacement lines */
- ita = TD; /* start of attribute lines to be blanked out */
- for (i = 0; i < n; i++)
- {
- ta = ita->text;
- tt = itt->text;
- for (j = 0; j <= VSIw->allwidth; j++)
- {
- *tt++ = ' ';
- *ta++ = VSIclrattrib;
- } /* for */
- ita = ita->next;
- itt = itt->next;
- } /* for */
-
- VSIw->scrntop = ts; /* new topmost line (if it's changed) */
- /* re-sync screen arrays */
- VSIlistndx(ts, as);
- if (VSIw->Rtop >= 0)
- /* make sure vistop still points to same line position
- on screen that it did before */
- VSIw->vistop = VSIw->linest[VSIw->Rtop];
- /* and actually display the change on-screen */
- VSIcdellines(VSIwn, s, VSIw->bottom, n, -1); /* Cancel current selection */
- } /* VSIdellines */
-
- void VSIinslines
- (
- int n, /* how many to insert */
- int s /* where to insert them, -ve => line containing cursor */
- )
- /* inserts the specified number of blank lines, scrolling the
- remaining ones down, and dropping off any that fall off the
- end of the scrolling region. */
- {
- int i, j;
- char *ta, *tt;
- VSlinePtr as, ts, TD, BD, TI, BI, itt, ita;
-
- if (s < 0)
- s = VSIw->y;
- if (s + n - 1 > VSIw->bottom)
- /* don't bother inserting more than scrolling region can hold */
- n = VSIw->bottom - s + 1;
-
- /* find new tops of screen arrays */
- if (s == 0 && n <= VSIw->lines)
- {
- /* element for first blank line being inserted */
- ts = VSIw->linest[VSIw->bottom - n + 1];
- as = VSIw->attrst[VSIw->bottom - n + 1];
- }
- else
- {
- /* top line unaffected, or entire screen is being wiped */
- ts = VSIw->linest[0];
- as = VSIw->attrst[0];
- } /* if */
-
- BI = VSIw->linest[s]; /* insert blank lines before this one */
- TI = BI->prev; /* insert them after this one */
- TD = VSIw->linest[VSIw->bottom - n + 1]; /* topmost line to delete */
- BD = VSIw->linest[VSIw->bottom]; /* bottommost line to delete */
- itt = TD; /* start of text lines to be blanked out */
- /* the space occupied by the deleted lines will be reused for
- the new blank lines */
- if (TD != BI && TI != BD)
- /* new and deleted lines not contiguous -- move the space
- to its new position */
- VSIlistmove(TD, BD, TI, BI);
-
- BI = VSIw->attrst[s]; /* insert new lines before this one */
- TI = BI->prev; /* insert them after this one */
- TD = VSIw->attrst[VSIw->bottom - n + 1]; /* topmost line to delete */
- BD = VSIw->attrst[VSIw->bottom]; /* bottommost line to delete */
- /* do the same rearrangement on the attribute lines */
- if (TD != BI && TI != BD)
- /* new and deleted lines not contiguous -- move the space
- to its new position */
- VSIlistmove(TD, BD, TI, BI);
-
- /* blank out the newly-inserted lines */
- ita = TD; /* start of attribute lines to be blanked out */
- for (i = 0; i < n; i++)
- {
- tt = itt->text;
- ta = ita->text;
- for (j = 0; j <= VSIw->allwidth; j++)
- {
- *tt++ = ' ';
- *ta++ = VSIclrattrib;
- }
- itt = itt->next;
- ita = ita->next;
- } /* for */
-
- VSIw->scrntop = ts;
- VSIlistndx(ts, as); /* re-sync screen arrays */
- if (VSIw->Rtop >= 0)
- /* make sure vistop still points to same line position
- on screen that it did before */
- VSIw->vistop = VSIw->linest[VSIw->Rtop];
- /* update display to match reality */
- VSIcinslines(VSIwn, s, VSIw->bottom, n, -1); /* Destroy selection area if this is called tooo */
- } /* VSIinslines */
-
- void VSIscroll
- (
- void
- )
- /* scrolls scrolling region up one line. */
- {
- register char *temp, *tempa;
- VSlinePtr tmp;
- register int i;
- int tx1, tx2, ty1, ty2, tn, offset;
- short theBottom; /* NCSA 2.5: the correct screen bottom */
-
- if (VSIw->y > VSIw->lines) /* BYU - replaces BYU modification below */
- return; /* BYU */
-
- tx1 = ty1 = 0;
- tn = 132;
- if (!VSIclip(&tx1, &ty1, &tx2, &ty2, &tn, &offset))
- /* top line of screen is visible */
- RSdrawsep(VSIwn, ty1, 1); /* Draw Separator */
-
-
- if ((!VSIw->savelines) /* no scrollback */ || (VSIw->top != 0) /* NCSA 2.5 */
- || ((VSIw->bottom != VSIw->lines) && !VSIw->forcesave)) /* NCSA 2.5 */
- /* region being scrolled is not entire screen */
-
- /* no saving of lines */
- VSIdellines(1, VSIw->top);
- else
- {
- /* scrolling region is entire screen, and lines are being saved off top */
- if (VSIw->linest[VSIw->lines]->next == 0L)
- {
- /* all currently-allocated scrollback lines have been used, but
- scrollback buffer isn't at its full size -- allocate some more
- space */
- i = VSIw->maxlines - VSIw->numlines; /* number of lines that can be allocated */
- if (i > ScrollbackQuantum)
- i = ScrollbackQuantum; /* don't bother allocating more than this at once */
- if ((i > 0) && (tmp = VSInewlines(i)) != 0L)
- {
- /* link newly-allocated lines into the list */
- VSIw->linest[VSIw->lines]->next = tmp;
- tmp->prev = VSIw->linest[VSIw->lines];
- VSIw->numlines++; /* use one of the newly-allocated scrollback lines */
- RSbufinfo(VSIwn, VSIw->numlines, VSIw->Rtop, VSIw->Rbottom); /* update vertical scroll bar accordingly */
- }
- else
- {
- /* not enough memory to extend scrollback buffer--reuse
- oldest line and give up on future extensions */
- VSIw->linest[VSIw->lines]->next = VSIw->buftop; /* Make it circular */
- VSIw->buftop->prev = VSIw->linest[VSIw->lines];
- VSIw->buftop = VSIw->buftop->next; /* step one forward */
- } /* if */
- }
- else
- {
- /* either there's allocated, but not yet used, space at
- VSIw->linest[VSIw->lines]->next, or the text line list
- is circular. Either way, don't do any new scrollback
- allocation. */
- if (VSIw->linest[VSIw->lines]->next == VSIw->buftop)
- /* scrollback buffer is at full size--reuse oldest line */
- VSIw->buftop = VSIw->buftop->next;
- else
- {
- /* haven't used up all the space I allocated last time */
- VSIw->numlines++; /* count another line */
- RSbufinfo(VSIwn, VSIw->numlines, VSIw->Rtop, VSIw->Rbottom); /* update vertical scroll bar accordingly */
- } /* if */
- } /* if */
-
- VSIw->scrntop = VSIw->scrntop->next; /* scroll the screen buffer */
- VSIlistndx(VSIw->scrntop, VSIw->attrst[1]); /* update screen arrays */
- /* reflect the change in the display by scrolling up the visible
- part of the on-screen area, if any */
-
- if (VSIw->forcesave) theBottom = VSIw->bottom; /* NCSA 2.5: get the correct scroll rgn */
- else theBottom = VSIw->Rbottom; /* NCSA 2.5: just use whole screen */
-
- if (VSIcdellines(VSIwn, VSIw->Rtop, theBottom, 1, 1)) /* NCSA 2.5 */
- {
- /* no part of on-screen area is visible */
- if (VSIw->Rtop > -VSIw->numlines)
- /* update bounds of visible region to be consistent
- with portion of scrollback buffer still being displayed */
- {
- VSIw->Rtop--;
- VSIw->Rbottom--;
- }
- else
- {
- /* displaying right from top of scrollback buffer. Topmost
- line being shown has in fact vanished. Update the display
- to show this fact. */
- VSIw->vistop = VSIw->vistop->next;
- RSdellines(VSIwn, 0, VSIw->Rbottom - VSIw->Rtop, 1, 1);
- } /* if */
- }
- else
- VSIw->vistop = VSIw->vistop->next; /* consistent with changed display */
- /* blank out newly-revealed bottom line */
- tempa = VSIw->attrst[VSIw->lines]->text;
- temp = VSIw->linest[VSIw->lines]->text;
- for (i = 0; i <= VSIw->allwidth; i++)
- {
- *temp++ = ' ';
- *tempa++ = 0;
- } /* for */
- } /* if */
- tx1 = ty1 = 0;
- tn = 132;
- if (!VSIclip(&tx1, &ty1, &tx2, &ty2, &tn, &offset))
- RSdrawsep(VSIwn, ty1, 1); /* Draw Separator */
- } /* VSIscroll */
-
- void VSIindex
- (
- void
- )
- /* moves cursor down one line, unless it's at the bottom of
- the scrolling region, in which case scrolls up one. */
- {
- if (VSIw->y == VSIw->bottom) /* BYU - changed "==" to ">=" and back again */
- VSIscroll();
- else if (VSIw->y < VSIw->lines) /* BYU - added "if ... " */
- VSIw->y++;
- } /* VSIindex */
-
- VSIwrapnow(xp, yp)
- int *xp, *yp;
- /* checks current cursor position for VSIw to see if
- it's within bounds, wrapping to next line if not.
- Returns correct cursor position in either case in *xp
- and *yp. */
- {
- if (VSIw->x > VSIw->maxwidth)
- {
- VSIw->x = 0;
- VSIindex();
- } /* if */
- *xp = VSIw->x;
- *yp = VSIw->y;
- } /* VSIwrapnow */
-
- void VSIeeol
- (
- void
- )
- /* erases characters to the end of the current line. */
- {
- char
- *tt,
- *ta;
- int
- x1 = VSIw->x,
- y1 = VSIw->y,
- x2 = VSIw->maxwidth,
- y2 = VSIw->y,
- n = -1,
- offset;
- int
- i;
-
- VSIwrapnow(&x1, &y1);
- y2 = y1;
- /* clear out screen line */
- ta = &VSIw->attrst[y1]->text[x1];
- tt = &VSIw->linest[y1]->text[x1];
- for (i = VSIw->allwidth - x1 + 1; i > 0; i--)
- {
- *ta++ = VSIclrattrib;
- *tt++ = ' ';
- }
- /* update display */
- if (!VSIclip(&x1, &y1, &x2, &y2, &n, &offset))
- RSerase(VSIwn, x1, y1, x2, y2);
- } /* VSIeeol */
-
- void VSIdelchars
- (
- int x /* how many characters to delete */
- )
- /* deletes characters at the current cursor position onwards,
- moving the remainder of the line to the left. */
- {
- int
- i;
- int
- x1 = VSIw->x,
- y1 = VSIw->y,
- x2 = VSIw->maxwidth,
- y2 = VSIw->y,
- n = -1,
- offset;
- char
- *tempa,
- *temp;
-
- VSIwrapnow(&x1, &y1);
- y2 = y1;
-
- if (x > VSIw->maxwidth)
- x = VSIw->maxwidth;
- tempa = VSIw->attrst[y1]->text;
- temp = VSIw->linest[y1]->text;
- for (i = x1; i <= VSIw->maxwidth - x; i++)
- {
- /* move remainder of line to the left */
- temp[i] = temp[x + i];
- tempa[i] = tempa[x + i];
- }
- for (i = VSIw->maxwidth - x + 1; i <= VSIw->allwidth; i++)
- {
- /* insert blank characters after end of line */
- temp[i] = ' ';
- tempa[i] = VSIclrattrib;
- }
- /* update display */
- if (!VSIclip(&x1, &y1, &x2, &y2, &n, &offset))
- {
- if (VSIw->VSIDC)
- RSdelchars(VSIwn, x1, y1, x);
- else
- /* redraw from cursor position to end of line.
- Trouble is, this isn't going to preserve the
- right attributes. */
- RSdraw
- (
- VSIwn, x1, y1, VSIw->attrib, n,
- &VSIw->linest[y1]->text[x1]
- );
- } /* if */
- } /* VSIdelchars */
-
- void VSIfreelinelist
- (
- VSlinePtr listhead
- )
- /* frees up the list of line elements pointed to by listhead. */
- {
- register VSlinePtr
- ThisElt, NextElt, ToFree;
-
- ThisElt = listhead;
- ToFree = nil;
- while (true)
- {
- if (ThisElt == nil)
- break;
- NextElt = ThisElt->next;
- if (ThisElt->mem)
- {
- ThisElt->next = ToFree;
- ToFree = ThisElt;
- } /* if */
- ThisElt = NextElt;
- if (ThisElt == listhead)
- break;
- } /* while */
- while (ToFree)
- {
- NextElt = ToFree->next;
- DisposPtr(ToFree->text);
- DisposPtr((Ptr) ToFree);
- ToFree = NextElt;
- } /* while */
- } /* VSIfreelinelist */
-
- void VSIfreelines
- (
- void
- )
- /* frees up all the memory allocated for screen and scrollback
- text lines for the current screen. */
- {
- VSIfreelinelist(VSIw->buftop);
- } /* VSIfreelines */
-
- void VSIrindex
- (
- void
- )
- /* moves cursor up one line, unless it's at the top of
- the scrolling region, in which case scrolls down one. */
- {
- if (VSIw->y == VSIw->top)
- VSIinslines(1, VSIw->top);
- else
- VSIw->y--;
- } /* VSIrindex */
-
- void VSIebol
- (
- void
- )
- /* erases characters from beginning of line to cursor. */
- {
- char
- *tt,
- *ta;
- int
- x1 = 0,
- y1 = VSIw->y,
- x2 = VSIw->x,
- y2 = VSIw->y,
- n = -1,
- offset;
- int
- i;
-
- VSIwrapnow(&x2, &y1);
- y2 = y1;
- /* clear from beginning of line to cursor */
- ta = &VSIw->attrst[y1]->text[0];
- tt = &VSIw->linest[y1]->text[0];
- for (i = 0; i <= x2; i++)
- {
- *ta++ = VSIclrattrib;
- *tt++ = ' ';
- }
- /* update display */
- if (!VSIclip(&x1, &y1, &x2, &y2, &n, &offset))
- RSerase(VSIwn, x1, y1, x2, y2);
- } /* VSIebol */
-
- void VSIel
- (
- int s /* line to clear, -ve => line containing cursor */
- )
- /* erases the specified line. */
- {
- char
- *tt,
- *ta;
- int
- x1 = 0,
- y1 = s,
- x2 = VSIw->maxwidth,
- y2 = s,
- n = -1,
- offset;
- int
- i;
-
- if (s < 0)
- {
- VSIwrapnow(&x1, &y1);
- s = y2 = y1;
- x1 = 0;
- } /* if */
- /* clear out line */
- ta = &VSIw->attrst[s]->text[0];
- tt = &VSIw->linest[s]->text[0];
- for(i = 0; i <= VSIw->allwidth; i++)
- {
- *ta++ = VSIclrattrib;
- *tt++ = ' ';
- }
- /* update display */
- if (!VSIclip(&x1, &y1, &x2, &y2, &n, &offset))
- RSerase(VSIwn, x1, y1, x2, y2);
- } /* VSIel */
-
- void VSIeeos
- (
- void
- )
- /* erases characters from cursor to end of screen. */
- {
- int
- i;
- int
- x1 = 0,
- y1 = VSIw->y + 1,
- x2 = VSIw->maxwidth,
- y2 = VSIw->lines,
- n = -1,
- offset;
-
- VSIwrapnow(&x1, &y1);
- y1++;
- x1 = 0;
-
- i = y1;
-
- if (VSIw->forcesave) /* NCSA 2.5 */
- VSIscroff(); /* NCSA 2.5 */
-
-
- /* erase complete lines from screen */
- if (!VSIclip(&x1, &y1, &x2, &y2, &n, &offset))
- RSerase(VSIwn, x1, y1, x2, y2);
- /* blank out current line from cursor to end */
- VSIeeol(); /* this also erases the partial line on-screen */
- /* blank out remaining lines to end of screen */
- while (i <= VSIw->lines)
- {
- VSIelo(i);
- i++;
- } /* while */
- if (VSIw->y < VSIw->lines && (VSIw->x <= VSIw->maxwidth))
- /* erase the partial line (what--again??) */
- if (!VSIclip(&x1, &y1, &x2, &y2, &n, &offset))
- RSerase(VSIwn, x1, y1, x2, y2);
- } /* VSIeeos */
-
- void VSIebos
- (
- void
- )
- /* erases characters from beginning of screen to cursor. */
- {
- int
- i;
- int
- x1,
- y1,
- x2 = VSIw->maxwidth,
- y2,
- n = -1,
- offset;
-
- VSIwrapnow(&x1, &y1);
- y2 = y1 - 1;
- x1 = 0;
- y1 = 0;
- /* blank out current line from beginning to cursor */
- VSIebol(); /* this also erases the partial line on-screen */
- i = 0;
- /* blank out remaining lines from beginning of screen to previous line */
- while (i < (y2 + 1))
- {
- VSIelo(i);
- i++;
- } /* while */
- if (y2 >= 0)
- /* erase the partial line (what--again??) */
- if (!VSIclip(&x1, &y1, &x2, &y2, &n, &offset))
- RSerase(VSIwn, x1, y1, x2, y2);
- } /* VSIebos */
-
- void VSIrange
- (
- void
- )
- /* constrains cursor position to valid range (somewhere on the screen). */
- {
- int
- wrap = 0;
- if (VSIw->DECAWM)
- wrap = 1;
- if (VSIw->x < 0)
- VSIw->x = 0;
- if (VSIw->x > (VSIw->maxwidth + wrap))
- VSIw->x = VSIw->maxwidth + wrap;
- if (VSIw->y < 0)
- VSIw->y = 0;
- if (VSIw->y > VSIw->lines)
- VSIw->y = VSIw->lines;
- } /* VSIrange */
-
- void VTsendpos
- (
- void
- )
- /* sends an escape sequence representing the current cursor position. */
- {
- char
- tempbuf[19];
- int
- x = VSIw->x,
- y = VSIw->y;
-
- if (x > VSIw->maxwidth)
- {
- /* autowrap pending */
- x = 0;
- y++;
- }
- if (y > VSIw->lines)
- /* scroll pending (because of the autowrap) */
- y = VSIw->lines;
-
- sprintf(tempbuf, "\033[%d;%dR", y + 1, x + 1);
- RSsendstring(VSIwn, tempbuf, strlen(tempbuf));
- } /* VTsendpos */
-
- void VTsendstat
- (
- void
- )
- /* sends the terminal status string. */
- {
- RSsendstring(VSIwn, "\033[0n", 4);
- } /* VTsendstat */
-
- void VTsendident
- (
- void
- )
- /* sends an appropriate terminal identification sequence. */
- {
- #ifdef VT100RESP
- if (VSIw->allwidth > 80)
- RSsendstring(VSIwn, "\033[?4;6c", 7);
- else
- RSsendstring(VSIwn, "\033[?1;6c", 7);
- #endif VT100RESP
- if (isEightBit(VSIwn) && /* BYU 2.4.12 */
- ((theWorld.keyBoardType == envAExtendKbd) || /* BYU 2.4.12 */
- (theWorld.keyBoardType == envExtISOADBKbd))) /* BYU 2.4.12 */
- RSsendstring(VSIwn, "\033[?62;1;6c", 10); /* BYU 2.4.12 - VT200-series*/
- else /* BYU 2.4.12 */
- RSsendstring(VSIwn, "\033[?6c", 5); /* BYU 2.4.12 - VT102 */
- } /* VTsendident */
-
- void VTalign
- (
- void
- )
- /* fills screen with uppercase "E"s, for checking screen alignment. */
- /* Yeah, right. */
- {
- char *tt;
- int i, j;
-
- VSIes(); /* erase the screen */
- for (j = 0; j < VSIw->lines; j++)
- {
- tt = &VSIw->linest[j]->text[0];
- for (i = 0; i <= VSIw->maxwidth; i++)
- *tt++ = 'E';
- } /* for */
- /* update the display */
- VSredraw(VSIwn, 0, 0,
- (VSIw->Rright - VSIw->Rleft), (VSIw->Rbottom - VSIw->Rtop));
- } /* VTalign */
-
- void VSIapclear
- (
- void
- )
- /* initializes all the parameters for the current control
- sequence, and the current param index, to zero. */
- {
- int
- parmptr = maxparms;
- while (--parmptr >= 0)
- VSIw->parms[parmptr] = -1;
- VSIw->parmptr = 0;
- } /* VSIapclear */
-
- void VSIsetoption
- (
- int toggle /* 1 => set, 0 => reset */
- )
- /* sets/resets various options, as specified by the parms in
- the current control sequence. Note that this implementation
- will not set/reset more than one option at a time! */
- {
- int
- WindWidth = VSIw->Rright - VSIw->Rleft;
-
- switch (VSIw->parms[0])
- {
- case -2: /* DEC-private control sequence */
- switch (VSIw->parms[1])
- {
- case 1: /* cursor-key mode */
- VSIw->DECCKM = toggle;
- break;
- case 3: /* 80/132 columns */
- VSIw->x = VSIw->y = 0; /* home cursor */
- VSIes(); /* and clear screen */
- if (toggle) /* 132 column mode */
- VSIw->maxwidth = VSIw->allwidth;
- else
- VSIw->maxwidth = 79;
- /* update scroll bars */
- RSmargininfo(VSIwn, VSIw->maxwidth - WindWidth, VSIw->Rleft);
- break;
- case 6: /* origin mode */
- VSIw->DECORG = toggle;
- break;
- case 7: /* autowrap mode */
- VSIw->DECAWM = toggle;
- break;
- default:
- break;
- } /* switch */
- break;
- case 4: /* insert/replace character writing mode */
- VSIw->IRM = toggle;
- break;
- default:
- break;
- } /* switch */
- } /* VSIsetoption */
-
- int VSItab
- (
- void
- )
- /* advances VSIw->x to the next tab position. */
- {
- if (VSIw->x >= VSIw->maxwidth)
- {
- /* already at right margin */
- VSIw->x = VSIw->maxwidth;
- return(0);
- } /* if */
- VSIw->x++; /* advance at least one position */
- while ((VSIw->tabs[VSIw->x] != 'x') && (VSIw->x < VSIw->maxwidth))
- VSIw->x++;
- return(0);
- } /* VSItab */
-
- void VSIinschar
- (
- int x /* number of blanks to insert */
- )
- /* inserts the specified number of blank characters at the
- current cursor position, moving the rest of the line along,
- losing any characters that fall off the right margin.
- Does not update the display. */
- {
- int i, j;
- char *tempa, *temp;
-
- VSIwrapnow(&i, &j);
-
- tempa = VSIw->attrst[VSIw->y]->text;
- temp = VSIw->linest[VSIw->y]->text;
- for (i = VSIw->maxwidth - x; i >= VSIw->x; i--)
- {
- /* move along remaining characters on line */
- temp[x + i] =temp[i];
- tempa[x + i] = tempa[i];
- } /* for */
- for (i = VSIw->x; i < VSIw->x + x; i++)
- {
- /* insert appropriate number of blanks */
- temp[i] = ' ';
- tempa[i] = VSIclrattrib;
- } /* for */
- } /* VSIinschar */
-
- void VSIinsstring
- (
- int len,
- char *start
- )
- /* updates the screen to show insertion of a string of characters
- at the current cursor position. The text has already been
- inserted into the screen buffer. Also, the cursor position has
- already been updated, so the part needing redrawing begins at column
- (VSIw->x - len). */
- {
- if (VSIw->VSIDC)
- RSinsstring(VSIwn, VSIw->x - len, VSIw->y,
- VSIw->attrib, len, start);
- else
- /* redraw from beginning of text insertion to end of line.
- Trouble is, this isn't going to preserve the right attributes. */
- RSdraw(VSIwn, VSIw->x - len, VSIw->y, VSIw->attrib,
- VSIw->maxwidth - VSIw->x + len + 1, start);
- } /* VSIinsstring */
-
- void VSIsave
- (
- void
- )
- /* saves the current cursor position and attribute settings. */
- {
- VSIw->Px = VSIw->x;
- VSIw->Py = VSIw->y;
- VSIw->Pattrib = VSIw->attrib;
- } /* VSIsave */
-
- void VSIrestore
- (
- void
- )
- /* restores the last-saved cursor position and attribute settings. */
- {
- if (VSIw->Pattrib < 0)
- /* no previous save */
- return;
-
- VSIw->x = VSIw->Px;
- VSIw->y = VSIw->Py;
- VSIrange();
- VSIw->attrib = VSinattr(VSIw->Pattrib); /* hmm, this will clear the graphics character set selection */
- } /* VSIrestore */
-
- void VSIdraw
- (
- int VSIwn, /* window number */
- int x, /* starting column */
- int y, /* line on which to draw */
- int a, /* text attributes */
- int len, /* length of text to draw */
- char *c /* pointer to text */
- )
- /* displays a piece of text (assumed to fit on a single line) on a
- screen, using the specified attributes, and clipping to the
- current visible region. Highlights any part of the text lying
- within the current selection. */
- {
- int x2, y2, offset;
-
- if (!VSIclip(&x, &y, &x2, &y2, &len, &offset))
- RSdraw(VSIwn, x, y, a, len, c + offset);
- } /* VSIdraw */
-