Example #1
0
int
show_text(const char *directory, const char *file_name, const char *header)
{
	struct stat sb;
	FILE *fp;
	int ch, cnt;
	char *p, lastc;
	int fd, nr;

	lastc = '\0';

	(void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name);
	if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) ||
	    sb.st_size == 0)
		return(0);

	/* If short enough, and no newlines, show it on a single line.*/
	if (sb.st_size <= LINE_LEN - strlen(header) - 5) {
		nr = read(fd, tbuf, sizeof(tbuf));
		if (nr <= 0) {
			(void)close(fd);
			return(0);
		}
		for (p = tbuf, cnt = nr; cnt--; ++p)
			if (*p == '\n')
				break;
		if (cnt <= 1) {
			if (*header != '\0')
				(void)printf("%s: ", header);
			for (p = tbuf, cnt = nr; cnt--; ++p)
				if (*p != '\r')
					vputc(lastc = *p);
			if (lastc != '\n')
				(void)putchar('\n');
			(void)close(fd);
			return(1);
		}
		else
			(void)lseek(fd, 0L, SEEK_SET);
	}
	if ((fp = fdopen(fd, "r")) == NULL)
		return(0);
	if (*header != '\0')
		(void)printf("%s:\n", header);
	while ((ch = getc(fp)) != EOF)
		if (ch != '\r')
			vputc(lastc = ch);
	if (lastc != '\n')
		(void)putchar('\n');
	(void)fclose(fp);
	return(1);
}
Example #2
0
/*
 * Put out a control sequence to the terminal.
 */
static void
vputs(char *cp)
{

	while (*cp)
		vputc(*cp++);
}
Example #3
0
/*
 * Rrrrringgggggg.
 * If possible, use flash (VB).
 */
void
beep(void)
{

	if (VB)
		vputp(VB, 0);
	else
		vputc(CTRL('g'));
}
Example #4
0
/*
 * Put a character with possible tracing.
 */
int
vputch(int c)
{

#ifdef TRACE
	if (trace)
		tracec(c);
#endif
	return vputc(c);
}
Example #5
0
/*
 * Get a line into genbuf after gcursor.
 * Cnt limits the number of input characters
 * accepted and is used for handling the replace
 * single character command.  Aescaped is the location
 * where we stick a termination indicator (whether we
 * ended with an ESCAPE or a newline/return.
 *
 * We do erase-kill type processing here and also
 * are careful about the way we do this so that it is
 * repeatable.  (I.e. so that your kill doesn't happen,
 * when you repeat an insert if it was escaped with \ the
 * first time you did it.
 */
char *
vgetline(int cnt, char *gcursor, bool *aescaped)
{
	register int c, ch;
	register char *cp;
	int x, y, iwhite;
	char *iglobp;
	void (*OO)() = Outchar;

	/*
	 * Clear the output state and counters
	 * for autoindent backwards motion (counts of ^D, etc.)
	 * Remember how much white space at beginning of line so
	 * as not to allow backspace over autoindent.
	 */
	*aescaped = 0;
	ogcursor = gcursor;
	flusho();
	CDCNT = 0;
	HADUP = 0;
	HADZERO = 0;
	gobbled = 0;
	iwhite = whitecnt(genbuf);
	iglobp = vglobp;

	/*
	 * Carefully avoid using vinschar in the echo area.
	 */
	if (splitw)
		Outchar = vputchar;
	else {
		Outchar = vinschar;
		vprepins();
	}
	for (;;) {
		if (gobblebl)
			gobblebl--;
		if (cnt != 0) {
			cnt--;
			if (cnt == 0)
				goto vadone;
		}
		ch = c = getkey() & (QUOTE|TRIM);
		if (!iglobp) {

			/*
			 * Erase-kill type processing.
			 * Only happens if we were not reading
			 * from untyped input when we started.
			 * Map users erase to ^H, kill to -1 for switch.
			 */
			if (c == tty.c_cc[VERASE])
				c = CTRL('h');
			else if (c == tty.c_cc[VKILL])
				c = -1;
			switch (c) {

			/*
			 * ^?		Interrupt drops you back to visual
			 *		command mode with an unread interrupt
			 *		still in the input buffer.
			 *
			 * ^\		Quit does the same as interrupt.
			 *		If you are a ex command rather than
			 *		a vi command this will drop you
			 *		back to command mode for sure.
			 */
			case ATTN:
			case QUIT:
				ungetkey(c);
				goto vadone;

			/*
			 * ^H		Backs up a character in the input.
			 *
			 * BUG:		Can't back around line boundaries.
			 *		This is hard because stuff has
			 *		already been saved for repeat.
			 */
			case CTRL('h'):
bakchar:
				cp = gcursor - 1;
				if (cp < ogcursor) {
					beep();
					continue;
				}
				goto vbackup;

			/*
			 * ^W		Back up a white/non-white word.
			 */
			case CTRL('w'):
				wdkind = 1;
				for (cp = gcursor; cp > ogcursor && isspace((int)cp[-1]); cp--)
					continue;
				for (c = wordch(cp - 1); cp > ogcursor && wordof(c, cp - 1); cp--)
					continue;
				goto vbackup;

			/*
			 * users kill	Kill input on this line, back to
			 *		the autoindent.
			 */
			case -1:
				cp = ogcursor;
vbackup:
				if (cp == gcursor) {
					beep();
					continue;
				}
				endim();
				*cp = 0;
				c = cindent();
				vgotoCL(qcolumn(cursor - 1, genbuf));
				if (doomed >= 0)
					doomed += c - cindent();
				gcursor = cp;
				continue;

			/*
			 * \		Followed by erase or kill
			 *		maps to just the erase or kill.
			 */
			case '\\':
				x = destcol, y = destline;
				ex_putchar('\\');
				vcsync();
				c = getkey();
				if (c == tty.c_cc[VERASE]
				    || c == tty.c_cc[VKILL]) {
					vgoto(y, x);
					if (doomed >= 0)
						doomed++;
					goto def;
				}
				ungetkey(c), c = '\\';
				goto noput;

			/*
			 * ^Q		Super quote following character
			 *		Only ^@ is verboten (trapped at
			 *		a lower level) and \n forces a line
			 *		split so doesn't really go in.
			 *
			 * ^V		Synonym for ^Q
			 */
			case CTRL('q'):
			case CTRL('v'):
				x = destcol, y = destline;
				ex_putchar('^');
				vgoto(y, x);
				c = getkey();
				if (c != NL) {
					if (doomed >= 0)
						doomed++;
					goto def;
				}
				break;
			}
		}

		/*
		 * If we get a blank not in the echo area
		 * consider splitting the window in the wrapmargin.
		 */
		if (c == ' ' && !splitw) {
			if (gobblebl) {
				gobbled = 1;
				continue;
			}
			if (value(WRAPMARGIN) && outcol >= WCOLS - value(WRAPMARGIN)) {
				c = NL;
				gobblebl = 2;
			}
		}
		switch (c) {

		/*
		 * ^M		Except in repeat maps to \n.
		 */
		case CR:
			if (vglobp)
				goto def;
			c = '\n';
			/* presto chango ... */

		/*
		 * \n		Start new line.
		 */
		case NL:
			*aescaped = c;
			goto vadone;

		/*
		 * escape	End insert unless repeat and more to repeat.
		 */
		case ESCAPE:
			if (vglobp && *vglobp)
				goto def;
			goto vadone;

		/*
		 * ^D		Backtab.
		 * ^T		Software forward tab.
		 *
		 *		Unless in repeat where this means these
		 *		were superquoted in.
		 */
		case CTRL('d'):
		case CTRL('t'):
			if (vglobp)
				goto def;
			/* fall into ... */

		/*
		 * ^D|QUOTE	Is a backtab (in a repeated command).
		 */
		case CTRL('d') | QUOTE:
			*gcursor = 0;
			cp = vpastwh(genbuf);
			c = whitecnt(genbuf);
			if (ch == CTRL('t')) {
				/*
				 * ^t just generates new indent replacing
				 * current white space rounded up to soft
				 * tab stop increment.
				 */
				if (cp != gcursor)
					/*
					 * BUG:		Don't hack ^T except
					 *		right after initial
					 *		white space.
					 */
					continue;
				cp = genindent(iwhite = backtab(c + value(SHIFTWIDTH) + 1));
				ogcursor = cp;
				goto vbackup;
			}
			/*
			 * ^D works only if we are at the (end of) the
			 * generated autoindent.  We count the ^D for repeat
			 * purposes.
			 */
			if (c == iwhite && c != 0) {
				if (cp == gcursor) {
					iwhite = backtab(c);
					CDCNT++;
					ogcursor = cp = genindent(iwhite);
					goto vbackup;
				} else if (&cp[1] == gcursor &&
				    (*cp == '^' || *cp == '0')) {
					/*
					 * ^^D moves to margin, then back
					 * to current indent on next line.
					 *
					 * 0^D moves to margin and then
					 * stays there.
					 */
					HADZERO = *cp == '0';
					ogcursor = cp = genbuf;
					HADUP = 1 - HADZERO;
					CDCNT = 1;
					endim();
					back1();
					vputc(' ');
					goto vbackup;
				}
			}
			if (vglobp && vglobp - iglobp >= 2 &&
			    (vglobp[-2] == '^' || vglobp[-2] == '0')
			    && gcursor == ogcursor + 1)
				goto bakchar;
			continue;

		default:
			/*
			 * Possibly discard control inputs.
			 */
			if (!vglobp && junk(c)) {
				beep();
				continue;
			}
def:
			ex_putchar(c);
noput:
			if (gcursor > &genbuf[LBSIZE - 2])
				error("Line too long");
			*gcursor++ = c & TRIM;
			vcsync();
#ifdef LISP
			if (value(SHOWMATCH) && !iglobp)
				if (c == ')' || c == '}')
					lsmatch(gcursor);
#endif
			continue;
		}
	}
vadone:
	*gcursor = 0;
	Outchar = OO;
	endim();
	return (gcursor);
}
Example #6
0
// Build and pop up a buffer containing a list of all screens and their associated buffers.  Render buffer and return status.
int showScreens(Value *rp,int n) {
	Buffer *slistp;
	EScreen *scrp;			// Pointer to current screen to list.
	EWindow *winp;			// Pointer into current screens window list.
	uint wnum;
	StrList rpt;
	int windcol = 7;
	int filecol = 37;
	char *strp,wkbuf[filecol + 16];

	// Get a buffer and open a string list.
	if(sysbuf(text160,&slistp) != SUCCESS)
			// "Screens"
		return rc.status;
	if(vopen(&rpt,NULL,false) != 0)
		return vrcset();

	// Construct the header lines.
	if(vputs(text89,&rpt) != 0 || vputc('\n',&rpt) != 0 ||
	    // "Screen Window      Buffer                File"
	 vputs("------ ------  --------------------  -------------------------------",&rpt) != 0)
		return vrcset();

	// For all screens...
	scrp = sheadp;
	do {
		// Store the screen number.
		sprintf(wkbuf,"\n%4hu   ",scrp->s_num);
		strp = strchr(wkbuf,'\0');

		// List screen's window numbers and buffer names.
		wnum = 0;
		winp = scrp->s_wheadp;
		do {
			Buffer *bufp = winp->w_bufp;

			// Indent if not first time through.
			if(wnum != 0) {
				wkbuf[0] = '\n';
				strp = wkbuf + 1;
				do {
					*strp++ = ' ';
					} while(strp <= wkbuf + windcol);
				}

			// Store window number, buffer name, and filename.
			sprintf(strp,"%4u   %c%s",++wnum,(bufp->b_flags & BFCHGD) ? '*' : ' ',bufp->b_bname);
			strp = strchr(strp,'\0');
			if(bufp->b_fname != NULL)			// Pad if filename exists.
				do {
					*strp++ = ' ';
					} while(strp <= wkbuf + filecol);
			*strp = '\0';					// Save buffer and add filename.
			if(vputs(wkbuf,&rpt) != 0 ||
			 (bufp->b_fname != NULL && vputs(bufp->b_fname,&rpt) != 0))
				return vrcset();

			// On to the next window.
			} while((winp = winp->w_nextp) != NULL);

		// On to the next screen.
		} while((scrp = scrp->s_nextp) != NULL);

	// Add the results to the buffer.
	if(vclose(&rpt) != 0)
		return vrcset();
	if(bappend(slistp,rpt.sl_vp->v_strp) != SUCCESS)
		return rc.status;

	// Display results.
	return render(rp,n < 0 ? -2 : n,slistp,RENDRESET | (n != INT_MIN && n < -1 ? RENDALTML : 0));
	}
Example #7
0
/*
 * Move cursor to line y, column x, handling wraparound and scrolling.
 */
void
vgoto(register int y, register int x)
{
	register cell *tp;
	register int c;

	/*
	 * Fold the possibly too large value of x.
	 */
	if (x >= WCOLS) {
		y += x / WCOLS;
		x %= WCOLS;
	}
#ifdef	MB
	if (y >= 0 && y <= WLINES && mb_cur_max > 1 && !insmode) {
		while (x > 0 && (vtube[y][x]&(MULTICOL|TRIM)) == MULTICOL &&
				vtube[y][x-1] & MULTICOL &&
				(vtube[y][x-1]&(MULTICOL|TRIM)) != MULTICOL)
			x--;
	}
#endif	/* MB */
	if (y < 0)
		error(catgets(catd, 1, 238, "Internal error: vgoto"));
	if (outcol >= WCOLS) {
		if (AM) {
			outline += outcol / WCOLS;
			outcol %= WCOLS;
		} else
			outcol = WCOLS - 1;
	}

	/*
	 * In a hardcopy or glass crt open, print the stuff
	 * implied by a motion, or backspace.
	 */
	if (state == HARDOPEN || state == ONEOPEN) {
		if (y != outline)
			error(catgets(catd, 1, 239, "Line too long for open"));
		if (x + 1 < outcol - x || (outcol > x && !BS))
			destcol = 0, fgoto();
		tp = vtube[WBOT] + outcol;
		while (outcol != x)
			if (outcol < x) {
				if (*tp == 0)
					*tp = ' ';
				c = *tp++ & TRIM;
				vputc(c && (!OS || EO) ? c : ' ');
				outcol++;
			} else {
				if (BC)
					vputp(BC, 0);
				else
					vputc('\b');
				outcol--;
			}
		destcol = outcol = x;
		destline = outline;
		return;
	}

	/*
	 * If the destination position implies a scroll, do it.
	 */
	destline = y;
	if (destline > WBOT && (!splitw || destline > WECHO)) {
		endim();
		vrollup(destline);
	}

	/*
	 * If there really is a motion involved, do it.
	 * The check here is an optimization based on profiling.
	 */
	destcol = x;
	if ((destline - outline) * WCOLS != destcol - outcol) {
		if (!MI)
			endim();
		fgoto();
	}
}
Example #8
0
/*
 * Put the character c on the screen at the current cursor position.
 * This routine handles wraparound and scrolling and understands not
 * to roll when splitw is set, i.e. we are working in the echo area.
 * There is a bunch of hacking here dealing with the difference between
 * QUOTE, QUOTE|' ', and ' ' for CONCEPT-100 like terminals, and also
 * code to deal with terminals which overstrike, including CRT's where
 * you can erase overstrikes with some work.  CRT's which do underlining
 * implicitly which has to be erased (like CONCEPTS) are also handled.
 */
int
vputchar(register int c)
{
	register cell *tp;
	register int d, m, n;

#ifndef	BIT8
	c &= (QUOTE|TRIM);
#endif
#ifdef TRACE
	if (trace)
		tracec(c);
#endif
	/* Fix problem of >79 chars on echo line. */
	if (destcol >= WCOLS-1 && splitw && destline == WECHO)
		pofix();
#ifdef	MB
	if (mb_cur_max > 1) {
		if (c == MULTICOL)
			return c;
		/*
		 * If a multicolumn character extends beyond the screen
		 * width, it must be put on the next line. A tilde is
		 * printed as an indicator but must disappear when the
		 * text is moved at a later time.
		 */
		if (c == ('~'|INVBIT|QUOTE))
			c = '~'|INVBIT;
		else if (c == ('~'|INVBIT))
			return c;
		else if (destcol < WCOLS && destcol +
				colsc(c==QUOTE ? ' ' : c&TRIM&~MULTICOL) - 1
				>= WCOLS)
			vputchar('~'|INVBIT|QUOTE);
	}
#endif	/* MB */
	if (destcol >= WCOLS) {
		destline += destcol / WCOLS;
		destcol %= WCOLS;
	}
	if (destline > WBOT && (!splitw || destline > WECHO))
		vrollup(destline);
	tp = vtube[destline] + destcol;
	if (c == QUOTE) {
		if (insmode) {
			/*
			 * When in insert mode, tabs have to expand
			 * to real, printed blanks.
			 */
			c = ' ' | QUOTE;
			goto def;
		}
		if (*tp == 0) {
			/*
			 * A ``space''.
			 */
			if ((hold & HOLDPUPD) == 0)
				*tp = QUOTE;
			destcol++;
			return c;
		}
		/*
		 * A ``space'' ontop of a part of a tab.
		 */
		if (*tp & QUOTE) {
			destcol++;
			return c;
		}
		c = ' ' | QUOTE;
		goto def;
	}

#ifdef	notdef
#ifdef	BIT8
	if (c == ' ' | QUOTE) {
		c = ' ';
		goto def;
	}
#endif
#endif
	switch (c) {

	case '\t':
		vgotab();
		return c;

	case ' ':
		/*
		 * We can get away without printing a space in a number
		 * of cases, but not always.  We get away with doing nothing
		 * if we are not in insert mode, and not on a CONCEPT-100
		 * like terminal, and either not in hardcopy open or in hardcopy
		 * open on a terminal with no overstriking, provided,
		 * in all cases, that nothing has ever been displayed
		 * at this position.  Ugh.
		 */
		if (!insmode && !IN && (state != HARDOPEN || OS)
		&& (*tp&QUOTE)) {
			*tp = ' ';
			destcol++;
			return c;
		}
		goto def;

def:
	default:
		d = *tp & TRIM;
		/*
		 * Now get away with doing nothing if the characters
		 * are the same, provided we are not in insert mode
		 * and if we are in hardopen, that the terminal has overstrike.
		 */
		if ((d & ~MULTICOL) == (c & TRIM & ~MULTICOL) && !insmode &&
				(state != HARDOPEN || OS) && c != MULTICOL) {
			n = colsc(d);
			for (m = 1; m < n; m++)
				if ((tp[m] & (MULTICOL|TRIM)) != MULTICOL)
					break;
			if (m == n) {
				if ((hold & HOLDPUPD) == 0)
					*tp = c | (n > 1 ? MULTICOL : 0);
				destcol += n;
				return c;
			}
		}
		/*
		 * Backwards looking optimization.
		 * The low level cursor motion routines will use
		 * a cursor motion right sequence to step 1 character
		 * right.  On, e.g., a DM3025A this is 2 characters
		 * and printing is noticeably slower at 300 baud.
		 * Since the low level routines are not allowed to use
		 * spaces for positioning, we discover the common
		 * case of a single space here and force a space
		 * to be printed.
		 */
		if (destcol == outcol + 1 && tp[-1] == ' ' && outline == destline) {
			vputc(' ');
			outcol++;
		}

		/*
		 * This is an inline expansion a call to vcsync() dictated
		 * by high frequency in a profile.
		 */
		if (outcol != destcol || outline != destline)
			vgoto(destline, destcol);

		/*
		 * Deal with terminals which have overstrike.
		 * We handle erasing general overstrikes, erasing
		 * underlines on terminals (such as CONCEPTS) which
		 * do underlining correctly automatically (e.g. on nroff
		 * output), and remembering, in hardcopy mode,
		 * that we have overstruct something.
		 */
		if (!insmode && d && d != ' ' && d != (c & TRIM)) {
			if (EO && (OS || UL && (c == '_' || d == '_'))) {
				vputc(' ');
				outcol++, destcol++;
				back1();
			} else
				rubble = 1;
		}

		/*
		 * Unless we are just bashing characters around for
		 * inner working of insert mode, update the display.
		 */
		if ((hold & HOLDPUPD) == 0)
			*tp = c;

		/*
		 * In insert mode, put out the IC sequence, padded
		 * based on the depth of the current line.
		 * A terminal which had no real insert mode, rather
		 * opening a character position at a time could do this.
		 * Actually should use depth to end of current line
		 * but this rarely matters.
		 */
#ifdef	notdef
		if (insmode)
#else
		/*
		 * It seems today's termcap writers consider this
		 * an either-or situation; if both im and ic
		 * are used vi puts out additional spaces.
		 *
		 * SVR4 ex does not include this change. If it hits
		 * your terminal, change back to the old way and
		 * mail me a description.
		 *
		 * GR July 2000
		 */
		if (insmode && (!IM || !*IM))
#endif	/* !notdef */
		{
			n = colsc(c&TRIM);
			for (m = 0; m < n; m++)
				vputp(IC, DEPTH(vcline));
		}
		vputc(c & TRIM);

		/*
		 * In insert mode, IP is a post insert pad.
		 */
		if (insmode)
			vputp(IP, DEPTH(vcline));
		destcol++, outcol++;

		/*
		 * CONCEPT braindamage in early models:  after a wraparound
		 * the next newline is eaten.  It's hungry so we just
		 * feed it now rather than worrying about it.
		 * Fixed to use	return linefeed to work right
		 * on vt100/tab132 as well as concept.
		 */
		if (XN && outcol % WCOLS == 0) {
			vputc('\r');
			vputc('\n');
		}
	}
#ifdef	MB
	if (mb_cur_max > 1 && (d = colsc(c&TRIM&~MULTICOL)) > 1) {
		if ((hold & HOLDPUPD) == 0)
			*tp |= MULTICOL;
		while (--d) {
			if ((hold & HOLDPUPD) == 0)
				*++tp = MULTICOL;
			destcol++;
			outcol++;
		}
	}
#endif	/* MB */
	return c;
}