/* * s_io() - routines that do screen I/O or effect what we think is * on the screen. * * By G. R. (Fred) Walter watmath!watcgl!grwalter */ #include "stevie.h" /* * screen_ins(row, nlines, total_rows) - insert 'nlines' lines at 'row' * * NOTE: this routine assumes it is called with valid arguments. */ static void screen_ins(row, nlines, total_rows) int row; int nlines; int total_rows; { if (nlines < 1 || (row + nlines) > total_rows) return; #ifndef T_IL_B { int i; for (i = 0; i < nlines; i++) { windgoto(row, 0); outstr(T_IL); } } #else windgoto(row, 0); outstr(T_IL); if (nlines >= 10) outchar((char) (nlines / 10 + '0')); outchar((char) (nlines % 10 + '0')); outstr(T_IL_B); #endif /* delete any garbage that may have been shifted to the status line */ windgoto(total_rows - 1, 0); outstr(T_EL); } /* * screen_del(row, nlines, total_rows) - delete 'nlines' lines at 'row' * * NOTE: this routine assumes it is called with valid arguments. */ static void screen_del(row, nlines, total_rows) int row; int nlines; int total_rows; { if (nlines < 1 || (row + nlines) > total_rows) return; /* delete any garbage that may have been on the status line */ windgoto(total_rows - 1, 0); outstr(T_EL); #ifndef T_DL_B { int i; for (i = 0; i < nlines; i++) { windgoto(row, 0); outstr(T_DL); /* delete a line */ } } #else windgoto(row, 0); outstr(T_DL); if (nlines >= 10) outchar((char) (nlines / 10 + '0')); outchar((char) (nlines % 10 + '0')); outstr(T_DL_B); #endif } /* * screen_refresh() * * Based on the current value of Topchar, refresh the contents of the screen * and update Botchar. */ static void screen_refresh(type) int type; { char *ptr; int total_rows; int row; int col; LINE *memp; LPtr start; bool_t off_top; bool_t done; /* if TRUE, we hit the end of the file */ bool_t didline; /* if TRUE, we finished the last line */ int lno; /* number of the line we're doing */ int coff; int idx; int i; int j; if (NumLineSizes <= 0) type = NOT_VALID; if (!RedrawingDisabled) outstr(T_CI); off_top = FALSE; idx = 0; row = 0; total_rows = Rows - 1; memp = Topchar->linep; if ((type == VALID) || (type == VALID_TO_CURSCHAR)) { j = -1; for (i = 0; i < NumLineSizes; i++) { if (LinePointers[i] == memp) { j = i; break; } row += LineSizes[i]; } if (j == -1) { /* Are we off the top of the screen by one line ? */ if (memp->next == LinePointers[0]) { i = plines(Topchar->linep->s); if (i < (total_rows)) { off_top = TRUE; for (idx = NumLineSizes; idx > 0; idx--) { LinePointers[idx] = LinePointers[idx - 1]; LineSizes[idx] = LineSizes[idx - 1]; } LineSizes[idx] = (char) i; if (!RedrawingDisabled) screen_ins(0, i, Rows); } } row = 0; } else if (j == 0 && type == VALID) { if (!RedrawingDisabled) outstr(T_CV); return; } else { if (!RedrawingDisabled) screen_del(0, row, Rows); row = 0; for (;;) { LineSizes[idx] = LineSizes[j]; LinePointers[idx] = LinePointers[j]; if (type == VALID_TO_CURSCHAR) { if (LinePointers[idx] == Curschar->linep) { memp = LinePointers[idx]; break; } } j++; if (j >= NumLineSizes) { memp = LinePointers[idx]; if (memp->next != Fileend->linep) { row += LineSizes[idx]; idx++; memp = memp->next; } break; } row += LineSizes[idx]; idx++; } } } coff = 0; if (P(P_NU)) { coff = 8; start.linep = memp; lno = cntllines(Filemem, &start); } didline = TRUE; done = FALSE; for (;;) { ptr = format_line(memp->s, &col); i = 1 + ((col - 1) / Columns); if ((row + i) <= total_rows) { LinePointers[idx] = memp; LineSizes[idx++] = (char) i; if (!RedrawingDisabled) { windgoto(row, 0); if (P(P_NU)) outstr(mkline(lno++)); outstr(ptr); j = col + coff; col = j % Columns; if ((col != 0) || (j == 0)) { #ifdef T_END_L windgoto(row + i - 1, col); outstr(T_END_L); #else for (; col < Columns; col++) outchar(' '); #endif } } row += i; if (memp->next != Fileend->linep) { memp = memp->next; } else { done = TRUE; break; } if (off_top) break; } else { didline = FALSE; break; } } /* Do we have to do off the top of the screen processing ? */ if (off_top && !done) { row = 0; for (idx = 0; idx <= NumLineSizes && row < total_rows; idx++) { row += LineSizes[idx]; } idx--; if (row < total_rows) { done = TRUE; idx++; } else if (row > total_rows) { row -= LineSizes[idx]; didline = FALSE; memp = LinePointers[idx]; } else { didline = TRUE; memp = LinePointers[idx]->next; idx++; } } NumLineSizes = idx; /* * If we didn't hit the end of the file, and we didn't finish the last * line we were working on, then the line didn't fit. */ if (!done && !didline) { if (!RedrawingDisabled) { /* Clear the rest of the screen. */ #ifdef T_END_D windgoto(row, 0); outstr(T_END_D); #else screen_del(row, total_rows - row, Rows); windgoto(row, 0); #endif /* put '@'s on rows that are part of a line that's too long */ for (; row < total_rows; row++) outstr("@\n\r"); } Botchar->linep = memp; } else { if (!RedrawingDisabled && !off_top) { /* Clear the rest of the screen. */ #ifdef T_END_D windgoto(row, 0); outstr(T_END_D); #else screen_del(row, total_rows - row, Rows); windgoto(row, 0); #endif /* put '~'s on rows that aren't part of the file. */ for (; row < total_rows; row++) outstr("~\n\r"); } if (done) /* we hit the end of the file */ *Botchar = *Fileend; else Botchar->linep = memp; /* FIX - prev? */ } if (!RedrawingDisabled) outstr(T_CV); } /* * s_refresh() * * Based on the current value of Curschar, (if necessary) update Topchar and * Botchar and refresh the screen contensts. */ void s_refresh(type) int type; { LPtr *p; LPtr *pp; int i; int nlines; int refreshed; refreshed = FALSE; if (bufempty()) { /* special case - file is empty */ *Topchar = *Filemem; *Curschar = *Filemem; screen_refresh(NOT_VALID); return; } if (NumLineSizes < 0) { type = NOT_VALID; } if (type != VALID) { screen_refresh(type); refreshed = TRUE; type = VALID; } if (LINEOF(Curschar) < LINEOF(Topchar)) { nlines = cntllines(Curschar, Topchar); /* * if the cursor is above the top of the screen, put it at the top of * the screen.. */ *Topchar = *Curschar; Topchar->index = 0; /* * ... and, if we weren't very close to begin with, we scroll so that * the line is close to the middle. */ if (nlines > Rows / 3) { p = Topchar; for (i = 0; i < Rows / 3; i += plines(p->linep->s)) { pp = prevline(p); if (pp == NULL) break; p = pp; } *Topchar = *p; } screen_refresh(VALID); } else if (LINEOF(Curschar) >= LINEOF(Botchar)) { nlines = cntllines(Botchar, Curschar); /* * If the cursor is off the bottom of the screen, put it at the top * of the screen.. ... and back up */ if (nlines > Rows / 3) { p = Curschar; for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) { pp = prevline(p); if (pp == NULL) break; p = pp; } *Topchar = *p; } else { scrollup(nlines); } screen_refresh(VALID); } else if (refreshed == FALSE) { screen_refresh(type); } /* Check if we are below Botchar (this can occur). */ if (LINEOF(Curschar) == LINEOF(Botchar)) { pp = nextline(Topchar); if (pp != NULL) { Topchar->linep = pp->linep; screen_refresh(VALID); } } else if (LINEOF(Curschar) > LINEOF(Botchar)) { nlines = cntllines(Botchar, Curschar); /* * If the cursor is off the bottom of the screen, put it at the top * of the screen.. ... and back up */ if (nlines > Rows / 3) { p = Curschar; for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) { pp = prevline(p); if (pp == NULL) break; p = pp; } *Topchar = *p; } else { scrollup(nlines); } screen_refresh(VALID); } } /* * s_clear() - clear the screen and mark the stored information as invalid. */ void s_clear() { outstr(T_ED); /* clear the display */ S_NOT_VALID; } /* * Update_Botchar() * * Based on the current value of Topchar update Botchar. */ void Update_Botchar() { int row; LINE *memp; int total_rows; int i; row = 0; total_rows = Rows - 1; memp = Topchar->linep; for (;;) { i = plines(memp->s); if ((row + i) <= total_rows) { row += i; memp = memp->next; if (memp == Fileend->linep) break; } else { break; } } Botchar->linep = memp; MustUpdateBotchar = FALSE; } #ifdef DONTINCLUDEANYMORE /* * NotValidFromCurschar() * * Mark the lines in NumLinePointers and NumLineSizes from Curschar on as * not valid. */ void NotValidFromCurschar() { register int idx; register unsigned long num; S_VALID_TO_CURSCHAR; num = LINEOF(Curschar); for (idx = 0; idx < NumLineSizes; idx++) { if (LinePointers[idx]->num >= num) break; } NumLineSizes = idx; } #endif