/* * Real work for winning growing of window at top * when inserting in the middle of a partially full * screen on an intelligent terminal. We have as argument * the logical line number to be inserted after, and the offset * from that line where the insert will go. * We look at the picture of depths and positions, and if we can * delete some (blank) lines from the top of the screen so that * later inserts will not push stuff off the bottom. */ int vglitchup(int l, int o) { register struct vlinfo *vp = &vlinfo[l]; register int need; register int p = vp->vliny; short oldhold = 0, oldheldech = 0; bool glitched = 0; if (l < vcnt - 1) { need = p + vp->vdepth - (vp+1)->vliny; if (need > 0) { if (state == VISUAL && WTOP - ZERO >= need && AL && DL) { glitched++; WTOP -= need; WLINES = WBOT - WTOP + 1; p -= need; if (p + o == WTOP) { vp->vliny = WTOP; return (WTOP + o); } vdellin(WTOP, need, -1); oldheldech = heldech; oldhold = hold; hold |= HOLDECH; } vinslin((vp+1)->vliny, need, l); if (glitched) { hold = oldhold; heldech = oldheldech; } } } else vp[1].vliny = vp[0].vliny + vp->vdepth; return (p + o); }
/* * Open new lines. * * Tricky thing here is slowopen. This causes display updating * to be held off so that 300 baud dumb terminals don't lose badly. * This also suppressed counts, which otherwise say how many blank * space to open up. Counts are also suppressed on intelligent terminals. * Actually counts are obsoleted, since if your terminal is slow * you are better off with slowopen. */ void voOpen ( int c, /* mjm: char --> int */ register int cnt ) { register int ind = 0, i; short oldhold = hold; #ifdef SIGWINCH sigset_t set, oset; #endif if (value(SLOWOPEN) || value(REDRAW) && AL && DL) cnt = 1; #ifdef SIGWINCH sigemptyset(&set); sigaddset(&set, SIGWINCH); sigprocmask(SIG_BLOCK, &set, &oset); #endif vsave(); setLAST(); if (value(AUTOINDENT)) ind = whitecnt(linebuf); if (c == 'O') { vcline--; dot--; if (dot > zero) getDOT(); } if (value(AUTOINDENT)) { #ifdef LISPCODE if (value(LISP)) ind = lindent(dot + 1); #endif } killU(); prepapp(); if (FIXUNDO) vundkind = VMANY; if (state != VISUAL) c = WBOT + 1; else { c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline); if (c < ZERO) c = ZERO; i = LINE(vcline + 1) - c; if (i < cnt && c <= WBOT && (!AL || !DL)) vinslin(c, cnt - i, vcline); } *genindent(ind) = 0; vdoappend(genbuf); vcline++; oldhold = hold; hold |= HOLDROL; vopen(dot, c); hold = oldhold; if (value(SLOWOPEN)) /* * Oh, so lazy! */ vscrap(); else vsync1(LINE(vcline)); cursor = linebuf; linebuf[0] = 0; vappend('o', 1, ind); #ifdef SIGWINCH sigprocmask(SIG_SETMASK, &oset, NULL); #endif }
/* * Insert character c at current cursor position. * Multi-character inserts occur only as a result * of expansion of tabs (i.e. inssize == 1 except * for tabs) and code assumes this in several place * to make life simpler. */ int vinschar(int c) /* int c; /\* mjm: char --> int */ { register int i; register cell *tp; char *OIM; bool OXN; int noim, filler = 0; insmc1 = colsc(c) - 1; if ((!IM || !EI) && ((hold & HOLDQIK) || !value(REDRAW) || value(SLOWOPEN))) { /* * Don't want to try to use terminal * insert mode, or to try to fake it. * Just put the character out; the screen * will probably be wrong but we will fix it later. */ if (c == '\t') { vgotab(); return c; } vputchar(c); #ifdef MB if (insmc1 == 0 && (vtube0[destcol]&(TRIM|MULTICOL))==MULTICOL) vtube0[destcol] = INVBIT; #endif /* MB */ if (DEPTH(vcline) * WCOLS + !value(REDRAW) > (destline - LINE(vcline)) * WCOLS + destcol) return c; /* * The next line is about to be clobbered * make space for another segment of this line * (on an intelligent terminal) or just remember * that next line was clobbered (on a dumb one * if we don't care to redraw the tail. */ if (AL) { vnpins(0); } else { c = LINE(vcline) + DEPTH(vcline); if (c < LINE(vcline + 1) || c > WBOT) return c; i = destcol; vinslin(c, 1, vcline); DEPTH(vcline)++; vigoto(c, i); vprepins(); } return c; } /* * Compute the number of positions in the line image of the * current line. This is done from the physical image * since that is faster. Note that we have no memory * from insertion to insertion so that routines which use * us don't have to worry about moving the cursor around. */ if (*vtube0 == 0) linend = 0; else { /* * Search backwards for a non-null character * from the end of the displayed line. */ i = WCOLS * DEPTH(vcline); if (i == 0) i = WCOLS; tp = vtube0 + i; while (*--tp == 0) if (--i == 0) break; linend = i + insmc1; } /* * We insert at a position based on the physical location * of the output cursor. */ inscol = destcol + (destline - LINE(vcline)) * WCOLS; insmc0 = 0; #ifdef MB i = 0; while (inscol+i < LBSIZE && vtube0[inscol+i]&MULTICOL && (vtube0[inscol+insmc0+i]&(MULTICOL|TRIM)) != MULTICOL) i++; while (inscol+insmc0+i < LBSIZE && (vtube0[inscol+insmc0+i]&(MULTICOL|TRIM)) == MULTICOL) insmc0++; #endif /* MB */ if (c == '\t') { /* * Characters inserted from a tab must be * remembered as being part of a tab, but we can't * use QUOTE here since we really need to print blanks. * QUOTE|' ' is the representation of this. */ inssiz = tabcol(inscol+insmc0, value(TABSTOP)) - inscol - insmc0; c = ' ' | QUOTE; } else inssiz = 1; /* * If the text to be inserted is less than the number * of doomed positions, then we don't need insert mode, * rather we can just typeover. */ if (inssiz + insmc1 <= doomed) { endim(); if (inscol + insmc0 != linend) doomed -= inssiz + insmc1; #ifdef MB if (insmc1 == 0 && c != '\t' && vtube0[inscol+insmc0] & MULTICOL) vtube0[inscol+insmc0] = INVBIT; #endif /* MB */ do vputchar(c); while (--inssiz); return c; } /* * Have to really do some insertion, thus * stake out the bounds of the first following * group of tabs, computing starting position, * ending position, and the number of ``spaces'' therein * so we can tell how much it will squish. */ tp = vtube0 + inscol + insmc0; for (i = inscol + insmc0; i < linend; i++) { if (*tp++ & QUOTE) { --tp; break; } } tabstart = tabend = i; tabslack = 0; while (tabend < linend) { i = *tp++; if ((i & QUOTE) == 0) break; if ((i & (TRIM|MULTICOL)) == 0) tabslack++; tabsize++; tabend++; } tabsize = tabend - tabstart; /* * For HP's and DM's, e.g. tabslack has no meaning. */ if (!IN) tabslack = 0; #ifdef IDEBUG if (trace) { fprintf(trace, "inscol %d, inssiz %d, tabstart %d, ", inscol, inssiz, tabstart); fprintf(trace, "tabend %d, tabslack %d, linend %d\n", tabend, tabslack, linend); } #endif OIM = IM; OXN = XN; noim = 0; #ifdef MB if (mb_cur_max > 1) { if (destcol + 1 + insmc1 == WCOLS + 1) { noim = 1; if (insmc1 == 1 && insmc0 == 0) filler = 1; } for (i = inscol; vtube0[i]; i++) if (i + 1 >= WCOLS && vtube0[i] & MULTICOL) { noim = 1; break; } } #endif /* MB */ if (noim) { endim(); IM = 0; XN = 0; } /* * The real work begins. */ slakused = 0; shft = 0; if (tabsize) { /* * There are tabs on this line. * If they need to expand, then the rest of the line * will have to be shifted over. In this case, * we will need to make sure there are no ``spaces'' * in the rest of the line (on e.g. CONCEPT-100) * and then grab another segment on the screen if this * line is now deeper. We then do the shift * implied by the insertion. */ if (inssiz >= doomed + tabcol(tabstart, value(TABSTOP)) - tabstart) { if (IN) vrigid(); vneedpos(value(TABSTOP)); vishft(); } } else if (inssiz + insmc1 > doomed) /* * No tabs, but line may still get deeper. */ vneedpos(inssiz + insmc1 - doomed); /* * Now put in the inserted characters. */ viin(c); /* * Now put the cursor in its final resting place. */ destline = LINE(vcline); destcol = inscol + inssiz + insmc1 + filler; vcsync(); if (IM != OIM) { IM = OIM; XN = OXN; } return c; }