Пример #1
0
// Write "== " to mode line and return count.
static int wupd_tab(int lchar) {

	vtputc(lchar);
	vtputc(lchar);
	vtputc(' ');
	return 3;
	}
Пример #2
0
// Update the current line to the virtual screen in given window.
static void vupd_dotline(EWindow *winp) {
	Line *lnp;		// Line to update.
	int sline;		// Physical screen line to update.
	int i;

	// Search down to the line we want...
	lnp = winp->w_face.wf_toplnp;
	sline = winp->w_toprow;
	while(lnp != winp->w_face.wf_dot.lnp) {
		++sline;
		lnp = lforw(lnp);
		}

	// and update the virtual line.
	vscreen[sline]->v_flags |= VFCHGD;
	taboff = winp->w_face.wf_fcol;
	vtmove(sline,-taboff);

	// Move each char of line to virtual screen until at end.
	for(i = 0; i < lused(lnp); ++i)
		vtputc(lgetc(lnp,i));
#if COLOR
	vscreen[sline]->v_rfcolor = winp->w_face.wf_fcolor;
	vscreen[sline]->v_rbcolor = winp->w_bcolor;
#endif
	vteeol();
	taboff = 0;
	}
Пример #3
0
// Write a string to the virtual screen.  Return number of characters written.
static int vtputs(char *strp) {
	int c;
	int count = 0;

	while((c = *strp++) != '\0')
		count += vtputc(c);
	return count;
	}
Пример #4
0
// Write a character to the virtual screen.  The virtual row and column are updated.  Return number of characters written.  If
// we are not yet at the left edge, don't write it.  If the line is too long put a "$" in the last column.  This routine only
// (1), puts printing characters into the virtual terminal buffers; and (2), checks for column overflow.
static int vtputc(int c) {
	Video *vp;		// Pointer to line being updated.
	int vtcol0 = vtcol;

	// Defeat automatic sign extension.
	c &= 0xff;

	// Line receiving this character.
	vp = vscreen[vtrow];

	if(vtcol >= (int) term.t_ncol) {

		// We are at the right edge!
		++vtcol;
		vp->v_text[term.t_ncol - 1] = '$';
		}
	else if(c == '\t') {
		// Output a hardware tab as the right number of spaces.
		do {
			vtputc(' ');
			} while(((vtcol + taboff) % (htabsize)) != 0);
		}
	else if(c < 0x20 || c == 0x7F) {

		// Control character.
		vtputc('^');
		vtputc(c ^ 0x40);
		}
	else if(c > 0x7f && (modetab[MDR_GLOBAL].flags & MDESC8)) {
		char wkbuf[5],*strp = wkbuf;

		// Display character with high bit set symbolically.
		sprintf(wkbuf,"<%.2X>",c);
		do {
			vtputc(*strp++);
			} while(*strp != '\0');
		}
	else {
		// It's normal, just put it in the screen map.
		if(vtcol >= 0)
			vp->v_text[vtcol] = c;
		++vtcol;
		}
	return vtcol - vtcol0;
	}
Пример #5
0
static void show_line(struct line *lp)
{
	int i = 0, len = llength(lp);

	while (i < len) {
		unicode_t c;
		i += utf8_to_unicode(lp->l_text, i, len, &c);
		vtputc(c);
	}
}
Пример #6
0
/*
 * Write a character to the virtual screen. The virtual row and
 * column are updated. If we are not yet on left edge, don't print
 * it yet. If the line is too long put a "$" in the last column.
 *
 * This routine only puts printing characters into the virtual
 * terminal buffers. Only column overflow is checked.
 */
static void vtputc(int c)
{
	struct video *vp;	/* ptr to line being updated */

	/* In case somebody passes us a signed char.. */
	if (c < 0) {
		c += 256;
		if (c < 0)
			return;
	}

	vp = vscreen[vtrow];

	if (vtcol >= term.t_ncol) {
		++vtcol;
		vp->v_text[term.t_ncol - 1] = '$';
		return;
	}

	if (c == '\t') {
		do {
			vtputc(' ');
		} while (((vtcol + taboff) & tabmask) != 0);
		return;
	}

	if (c < 0x20) {
		vtputc('^');
		vtputc(c ^ 0x40);
		return;
	}

	if (c == 0x7f) {
		vtputc('^');
		vtputc('?');
		return;
	}

	if (c >= 0x80 && c <= 0xA0) {
		static const char hex[] = "0123456789abcdef";
		vtputc('\\');
		vtputc(hex[c >> 4]);
		vtputc(hex[c & 15]);
		return;
	}
	
	if (vtcol >= 0)
		vp->v_text[vtcol] = c;
	++vtcol;
}
Пример #7
0
// Transfer all lines in given window to virtual screen.
static void vupd_all(EWindow *winp) {
	Line *lnp;		// Line to update.
	int sline;		// Physical screen line to update.
	int i;
	int nlines;		// Number of lines in the current window.

	// Search down the lines, updating them.
	lnp = winp->w_face.wf_toplnp;
	sline = winp->w_toprow;
	nlines = winp->w_nrows;
	taboff = winp->w_face.wf_fcol;
	while(sline < winp->w_toprow + nlines) {

		// Update the virtual line.
		vscreen[sline]->v_flags |= VFCHGD;
		vscreen[sline]->v_left = FARRIGHT;
		vscreen[sline]->v_right = 0;
		vtmove(sline,-taboff);

		// If we are not at the end...
		if(lnp != winp->w_bufp->b_hdrlnp) {
			for(i = 0; i < lused(lnp); ++i)
				vtputc(lgetc(lnp,i));
			lnp = lforw(lnp);
			}

		// Make sure we are on screen.
		if(vtcol < 0)
			vtcol = 0;

		// On to the next line.
#if COLOR
		vscreen[sline]->v_rfcolor = winp->w_face.wf_fcolor;
		vscreen[sline]->v_rbcolor = winp->w_bcolor;
#endif
		vteeol();
		++sline;
		}
	taboff = 0;
	}
Пример #8
0
// De-extend any line in any window that needs it.
static void supd_dex(void) {
	EWindow *winp;
	Line *lnp;
	int i,j;
	int nlines;		// Number of lines in the current window.

	winp = wheadp;
	do {
		lnp = winp->w_face.wf_toplnp;
		i = winp->w_toprow;
		nlines = winp->w_nrows;

		while(i < winp->w_toprow + nlines) {
			if(vscreen[i]->v_flags & VFEXT) {
				if(winp != curwp || lnp != winp->w_face.wf_dot.lnp || curcol < (int) term.t_ncol - 1) {
					if(lnp == winp->w_bufp->b_hdrlnp)
						vtmove(i,0);
					else {
						taboff = winp->w_face.wf_fcol;
						vtmove(i,-taboff);
						for(j = 0; j < lused(lnp); ++j)
							vtputc(lgetc(lnp,j));
						taboff = 0;
						}
					vteeol();

					// This line is no longer extended.
					vscreen[i]->v_flags &= ~VFEXT;
					vscreen[i]->v_flags |= VFCHGD;
					}
				}
			if(lnp != winp->w_bufp->b_hdrlnp)
				lnp = lforw(lnp);
			++i;
			}

		// Onward to the next window.
		} while((winp = winp->w_nextp) != NULL);
	}
Пример #9
0
// Update the extended line which the cursor is currently on at a column greater than the terminal width.  The line will be
// scrolled right or left to let the user see where the cursor is.
static void vupd_ext(void) {
	int rcursor;		// Real cursor location.
	Line *lnp;		// Pointer to current line.
	int j;			// Index into line.

	// Calculate what column the real cursor will end up in.
	rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;	// 10% width <= rcursor < 90%
	lbound = curcol - rcursor + 1;
	taboff = lbound + curwp->w_face.wf_fcol;

	// Write the current line to the virtual screen.
	vtmove(currow,-taboff);			// Start scanning offscreen.
	lnp = curwp->w_face.wf_dot.lnp;		// Line to output.
	for(j = 0; j < lused(lnp); ++j)		// Until the end-of-line.
		vtputc(lgetc(lnp,j));

	// Truncate the virtual line, restore tab offset.
	vteeol();
	taboff = 0;

	// and put a '$' in column 1.
	vscreen[currow]->v_text[0] = '$';
	}
Пример #10
0
// Redisplay the mode line for the window pointed to by winp.  If popbuf is NULL, display a fully-formatted mode line containing
// the current buffer's name and filename (but in condensed form if the current terminal width is less than 96 columns);
// otherwise, display only the buffer name and filename of buffer "popbuf".  This is the only routine that has any idea of how
// the mode line is formatted.  You can change the mode line format by hacking at this routine.  Called by "update" any time
// there is a dirty window.
void wupd_modeline(EWindow *winp,Buffer *popbuf) {
	int c;
	int n;				// Cursor position.
	Buffer *bufp;
	ModeSpec *msp;
	int lchar;
	int condensed = term.t_ncol < 80 ? -1 : term.t_ncol < 96 ? 1 : 0;
	char wkbuf[32];			// Work buffer.
	static struct {			// Mode display parameters.
		int leadch,trailch;
		uint flags;
		} *mdp,md[] = {
			{'(',')',0},
			{'[',']',0},
			{-1,-1,0}};

	n = winp->w_toprow + winp->w_nrows;		// Row location.

	// Note that we assume that setting REVERSE will cause the terminal driver to draw with the inverted relationship of
	// fcolor and bcolor, so that when we say to set the foreground color to "white" and background color to "black", the
	// fact that "reverse" is enabled means that the terminal driver actually draws "black" on a background of "white".
	// Makes sense, no?  This way, devices for which the color controls are optional will still get the "reverse" signals.
	vscreen[n]->v_left = 0;
	vscreen[n]->v_right = term.t_ncol;
#if COLOR
	vscreen[n]->v_flags |= VFCHGD | VFCOLOR;	// Redraw next time.
	vscreen[n]->v_rfcolor = 7;			// Black on.
	vscreen[n]->v_rbcolor = 0;			// White...
#else
	vscreen[n]->v_flags |= VFCHGD;			// Redraw next time.
#endif
	vtmove(n,0);					// Seek to right line.
	if(winp == curwp)				// Make the current buffer stand out.
		lchar = '=';
#if REVSTA
	else if(opflags & OPHAVEREV)
		lchar = ' ';
#endif
	else
		lchar = '-';

	// Full display?
	if(popbuf == NULL) {
		bufp = winp->w_bufp;
		vtputc((bufp->b_flags & BFTRUNC) ? '#' : lchar);	// "#" if truncated.
		vtputc((bufp->b_flags & BFCHGD) ? '*' : lchar);		// "*" if changed.
		vtputc((bufp->b_flags & BFNARROW) ? '<' : lchar);	// "<" if narrowed.
		vtputc(' ');
		n = 4;

		// Display program name and version.
		if(!condensed) {
			sprintf(wkbuf,"%s %s ",Myself,Version);
			n += vtputs(wkbuf);
			}

		// Are we horizontally scrolled?
		if(winp->w_face.wf_fcol > 0) {
			sprintf(wkbuf,"[<%d] ",winp->w_face.wf_fcol);
			n += vtputs(wkbuf);
			}

		// Display the screen number if bottom window and there's more than one screen.
		if(winp->w_nextp == NULL && scrcount() > 1) {
			sprintf(wkbuf,"S%hu ",cursp->s_num);
			n += vtputs(wkbuf);
			}

		// Display keyboard macro recording state.
		if(kmacro.km_state == KMRECORD)
			n += vtputs("*R* ");

		// Display the line and/or column point position if enabled and winp is current window.
		if(winp == curwp) {
			if(curbp->b_modes & MDLINE) {
				sprintf(wkbuf,"L:%ld ",getlinenum(bufp,winp->w_face.wf_dot.lnp));
				n += vtputs(wkbuf);
				}
			if(curbp->b_modes & MDCOL) {
				sprintf(wkbuf,"C:%d ",getccol());
				n += vtputs(wkbuf);
				}
			}

		// Display the modes, in short form if condensed display.
		md[0].flags = modetab[MDR_GLOBAL].flags & modetab[MDR_SHOW].flags;
		md[1].flags = winp->w_bufp->b_modes;
		mdp = md;
		do {
			msp = ((c = mdp->leadch) == '[') ? bmodeinfo : gmodeinfo;
			do {
				if(mdp->flags & msp->mask) {
					n += vtputc(c);
					c = ' ';
					if(condensed >= 0)
						n += vtputs(msp->mlname);
					else {
						n += vtputc(msp->mlname[0]);
						if(msp->mlname[1] != '\0')
							n += vtputc(msp->mlname[1]);
						}
					}
				} while((++msp)->name != NULL);
			if(c != mdp->leadch) {
				n += vtputc(mdp->trailch);
				n += vtputc(' ');
				}
			} while((++mdp)->leadch > 0);
#if 0
		// Display internal modes on modeline.
		vtputc(lchar);
		vtputc((winp->w_flags & WFCOLOR) ? 'C' : lchar);
		vtputc((winp->w_flags & WFMODE) ? 'M' : lchar);
		vtputc((winp->w_flags & WFHARD) ? 'H' : lchar);
		vtputc((winp->w_flags & WFEDIT) ? 'E' : lchar);
		vtputc((winp->w_flags & WFMOVE) ? 'V' : lchar);
		vtputc((winp->w_flags & WFFORCE) ? 'F' : lchar);
		vtputc(lchar);
		n += 8;
#endif
		n += wupd_tab(lchar);
		}
	else {
		n = 0;
		bufp = popbuf;
		vtputc(lchar);
		n += wupd_tab(lchar) + 1;
		}

	// Display the buffer name.
	n += vtputs(bufp->b_bname) + 1;
	vtputc(' ');

	// Display the filename in the remaining space using strfit().
	if(bufp->b_fname != NULL) {
		char wkbuf[TT_MAXCOLS];

		n += wupd_tab(lchar);
		if(condensed < 0) {
			vtputc(*text34);
				// "File: "
			vtputc(':');
			vtputc(' ');
			n += 3;
			}
		else
			n += vtputs(text34);
				// "File: "
		n += vtputs(strfit(wkbuf,term.t_ncol - n - 1,bufp->b_fname,0)) + 1;
		vtputc(' ');
		}

	// If it's the current window, not a pop-up, "pwd" mode, and room still available, display the working directory as
	// well.
	if(winp == curwp && popbuf == NULL && (modetab[MDR_GLOBAL].flags & MDWKDIR) && ((int) term.t_ncol - n) > 12) {
		char *wdp;
		char wkbuf[TT_MAXCOLS];

		n += wupd_tab(lchar);
		n += vtputs(text274);
			// "WD: "
		(void) getwkdir(&wdp,false);
		n += vtputs(strfit(wkbuf,term.t_ncol - n - 1,wdp,0)) + 1;
		vtputc(' ');
		}

	// Pad to full width.
	while(n < (int) term.t_ncol) {
		vtputc(lchar);
		++n;
		}
	}
Пример #11
0
// Display a pop-up window and page it for the user.  If altmodeline is true, display buffer name and filename (only) on bottom
// mode line.  If endprompt is true, wait for user to press a key before returning (regardless of page size).  Current bindings
// (if any) for backPage, forwPage, backLine, and forwLine commands are recognized as well as 'b' (backward page), 'f' or space
// (forward page), 'u' (backward half page), 'd' (forward half page), 'g' (goto first page), 'G' (goto last page), ESC or 'q'
// (exit), and '?' (help).  Any non-navigation key gets pushed back into the input stream to be interpeted later as a command. 
// Return status.
int bpop(Buffer *bufp,bool altmodeline,bool endprompt) {
	Line *lnp1,*lnp,*lpmax;
	int crow;		// Current screen row number.
	int disprows;		// Total number of display rows.
	int halfpage;		// Rows in a half page.
	int n;			// Rows to move.
	ushort ek;		// Input extended key.
	char *strp,*strpz;	// Line text pointers.
	char *hprompt = NULL;	// Help prompt;
	bool firstpass = true;

	// Display special mode line if requested.
	if(altmodeline) {

		// Find last window on screen and rewrite its mode line.
		wupd_modeline(wnextis(NULL),bufp);
		}

	// Set up and display a pop-up "window".
	disprows = term.t_nrow - 2;

	// Check if buffer will fit on one page and if not, set lpmax to first line of last page.
	lpmax = NULL;
	n = 0;
	for(lnp = lforw(bufp->b_hdrlnp); lnp != bufp->b_hdrlnp; lnp = lforw(lnp)) {
		if(++n > disprows) {

			// Find beginning of last page.
			lpmax = bufp->b_hdrlnp;
			n = disprows;
			do {
				lpmax = lback(lpmax);
				} while(--n > 0);
			break;
			}
		}

	// Begin at the beginning.
	lnp1 = lforw(bufp->b_hdrlnp);
	halfpage = disprows / 2;
	n = 0;

	// Display a page (beginning at line lnp1 + n) and prompt for a naviagtion command.  Loop until exit key entered or
	// endprompt is false and buffer fits on one page (lpmax is NULL).
	for(;;) {
		lnp = lnp1;

		// Moving backward?
		if(n < 0) {
			do {
				// At beginning of buffer?
				if(lpmax == NULL || lnp1 == lforw(bufp->b_hdrlnp))
					break;

				// No, back up one line.
				lnp1 = lback(lnp1);
				} while(++n < 0);
			}

		// Moving forward?
		else if(n > 0) {
			do {
				// At end of buffer or max line?
				if(lpmax == NULL || lnp1 == bufp->b_hdrlnp || lnp1 == lpmax)
					break;

				// No, move forward one line.
				lnp1 = lforw(lnp1);
				} while(--n > 0);
			}

		// Illegal command?
		if(n != 0 && lnp1 == lnp)

			// Yes, ignore it.
			n = 0;
		else {
			// Found first row ... display page.
			lnp = lnp1;
			crow = 0;
			do {
				// At end of buffer?
				if(lnp == bufp->b_hdrlnp) {

					// Yes, erase remaining lines on physical screen.
					while(crow < disprows) {
						vtmove(crow,0);
						vteeol();
#if COLOR
						vscreen[crow]->v_rfcolor = gfcolor;
						vscreen[crow]->v_rbcolor = gbcolor;
#endif
						vscreen[crow]->v_left = FARRIGHT;
						vscreen[crow]->v_right = 0;
#if COLOR
						vscreen[crow++]->v_flags |= VFCHGD | VFCOLOR;
#else
						vscreen[crow++]->v_flags |= VFCHGD;
#endif
						}
					break;
					}

				// Update the virtual screen image for this line.  Characters past right edge of screen won't be
				// displayed, so ignore those.
				vtmove(crow,0);
				strpz = (strp = ltext(lnp)) + (lused(lnp) <= (int) term.t_ncol ? lused(lnp) : term.t_ncol);
				while(strp < strpz)
					vtputc(*strp++);
				vteeol();
#if COLOR
				vscreen[crow]->v_rfcolor = gfcolor;
				vscreen[crow]->v_rbcolor = gbcolor;
#endif
				vscreen[crow]->v_left = FARRIGHT;
				vscreen[crow]->v_right = 0;
#if COLOR
				vscreen[crow++]->v_flags |= VFCHGD | VFCOLOR;
#else
				vscreen[crow++]->v_flags |= VFCHGD;
#endif
				// On to the next line.
				lnp = lforw(lnp);
				} while(crow < disprows);

			// Screen is full.  Copy the virtual screen to the physical screen.
			if(pupd_all(false) != SUCCESS)
				return rc.status;

			// Bail out if called from terminp() and one-page buffer.
			if(firstpass && !endprompt && lpmax == NULL)
				goto uexit;
			firstpass = false;
			}

		// Display prompt.
		mlputs(MLHOME | MLFORCE,hprompt != NULL ? hprompt : lpmax == NULL || lnp1 == lpmax ? text201 : ": ");
													// "End: "
		if(TTflush() != SUCCESS)
			return rc.status;

		// Get response.
		for(;;) {
			// Get a keystroke and decode it.
			if(getkey(&ek) != SUCCESS)
				return rc.status;

			// Exit?
			if(ek == (CTRL | '[') || ek == 'q')
				goto uexit;

			// Forward whole page?
			if(ek == ' ' || ek == 'f' || iscmd(ek,forwPage)) {
				n = disprows - overlap;
				break;
				}

			// Forward half page?
			if(ek == 'd') {
				n = halfpage;
				break;
				}

			// Backward whole page?
			if(ek == 'b' || iscmd(ek,backPage)) {
				n = overlap - disprows;
				break;
				}

			// Backward half page?
			if(ek == 'u') {
				n = -halfpage;
				break;
				}

			// Forward a line?
			if(iscmd(ek,forwLine)) {
				n = 1;
				break;
				}

			// Backward a line?
			if(iscmd(ek,backLine)) {
				n = -1;
				break;
				}

			// First page?
			if(ek == 'g') {
				if(lpmax == NULL || lnp1 == lforw(bufp->b_hdrlnp))
					n = -1;			// Force beep.
				else {
					lnp1 = lforw(bufp->b_hdrlnp);
					n = 0;
					}
				break;
				}

			// Last page?
			if(ek == 'G') {
				if(lpmax == NULL || lnp1 == lpmax)
					n = 1;			// Force beep.
				else {
					lnp1 = lpmax;
					n = 0;
					}
				break;
				}

			// Help?
			if(ek == '?') {
				StrList msg;

				// Get string list...
				if(vopen(&msg,NULL,false) != 0)
					return vrcset();

				// build prompt...
				if(vputs(text202,&msg) != 0)
						// "(<SPC>,f"
					return vrcset();
				if(hkey(&msg,forwPage,0) != SUCCESS)
					return rc.status;
				if(vputs(text203,&msg) != 0)
						// ") +page (b"
					return vrcset();
				if(hkey(&msg,backPage,0) != SUCCESS)
					return rc.status;
				if(vputs(text204,&msg) != 0)
						// ") -page (d) +half (u) -half"
					return vrcset();
				if(hkey(&msg,forwLine,'+') != SUCCESS || hkey(&msg,backLine,'-') != SUCCESS)
					return rc.status;
				if(vputs(text206,&msg) != 0)
						// " (g) first (G) last (ESC,q) quit (?) help: "
					return vrcset();

				// and display it.
				if(vclose(&msg) != 0)
					return vrcset();
				mlputs(MLHOME | MLFORCE,msg.sl_vp->v_strp);
				}
			else {
				// Other key.  "Unget" the key for reprocessing and return.
				tungetc(ek);
				goto uexit;
				}
			}
		}
uexit:
	uphard();
	if(endprompt)
		mlerase(MLFORCE);

	return rc.status;
	}