119304Speter/*-
219304Speter * Copyright (c) 1992, 1993, 1994
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996
519304Speter *	Keith Bostic.  All rights reserved.
619304Speter *
719304Speter * See the LICENSE file for redistribution information.
819304Speter */
919304Speter
1019304Speter#include "config.h"
1119304Speter
1219304Speter#ifndef lint
13254225Speterstatic const char sccsid[] = "$Id: getc.c,v 10.13 2011/12/27 00:49:31 zy Exp $";
1419304Speter#endif /* not lint */
1519304Speter
1619304Speter#include <sys/types.h>
1719304Speter#include <sys/queue.h>
1819304Speter#include <sys/time.h>
1919304Speter
2019304Speter#include <bitstring.h>
2119304Speter#include <ctype.h>
2219304Speter#include <limits.h>
2319304Speter#include <stdio.h>
2419304Speter#include <stdlib.h>
2519304Speter
2619304Speter#include "../common/common.h"
2719304Speter#include "vi.h"
2819304Speter
2919304Speter/*
3019304Speter * Character stream routines --
3119304Speter *	These routines return the file a character at a time.  There are two
3219304Speter *	special cases.  First, the end of a line, end of a file, start of a
3319304Speter *	file and empty lines are returned as special cases, and no character
3419304Speter *	is returned.  Second, empty lines include lines that have only white
3519304Speter *	space in them, because the vi search functions don't care about white
3619304Speter *	space, and this makes it easier for them to be consistent.
3719304Speter */
3819304Speter
3919304Speter/*
4019304Speter * cs_init --
4119304Speter *	Initialize character stream routines.
4219304Speter *
43281373Sbapt * PUBLIC: int cs_init(SCR *, VCS *);
4419304Speter */
4519304Speterint
46254225Spetercs_init(SCR *sp, VCS *csp)
4719304Speter{
4819304Speter	int isempty;
4919304Speter
5019304Speter	if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) {
5119304Speter		if (isempty)
5219304Speter			msgq(sp, M_BERR, "177|Empty file");
5319304Speter		return (1);
5419304Speter	}
5519304Speter	if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
5619304Speter		csp->cs_cno = 0;
5719304Speter		csp->cs_flags = CS_EMP;
5819304Speter	} else {
5919304Speter		csp->cs_flags = 0;
6019304Speter		csp->cs_ch = csp->cs_bp[csp->cs_cno];
6119304Speter	}
6219304Speter	return (0);
6319304Speter}
6419304Speter
6519304Speter/*
6619304Speter * cs_next --
6719304Speter *	Retrieve the next character.
6819304Speter *
69281373Sbapt * PUBLIC: int cs_next(SCR *, VCS *);
7019304Speter */
7119304Speterint
72254225Spetercs_next(SCR *sp, VCS *csp)
7319304Speter{
74254225Speter	CHAR_T *p;
7519304Speter
7619304Speter	switch (csp->cs_flags) {
7719304Speter	case CS_EMP:				/* EMP; get next line. */
7819304Speter	case CS_EOL:				/* EOL; get next line. */
7919304Speter		if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) {
8019304Speter			--csp->cs_lno;
8119304Speter			csp->cs_flags = CS_EOF;
8219304Speter		} else {
8319304Speter			csp->cs_bp = p;
8419304Speter			if (csp->cs_len == 0 ||
8519304Speter			    v_isempty(csp->cs_bp, csp->cs_len)) {
8619304Speter				csp->cs_cno = 0;
8719304Speter				csp->cs_flags = CS_EMP;
8819304Speter			} else {
8919304Speter				csp->cs_flags = 0;
9019304Speter				csp->cs_ch = csp->cs_bp[csp->cs_cno = 0];
9119304Speter			}
9219304Speter		}
9319304Speter		break;
9419304Speter	case 0:
9519304Speter		if (csp->cs_cno == csp->cs_len - 1)
9619304Speter			csp->cs_flags = CS_EOL;
9719304Speter		else
9819304Speter			csp->cs_ch = csp->cs_bp[++csp->cs_cno];
9919304Speter		break;
10019304Speter	case CS_EOF:				/* EOF. */
10119304Speter		break;
10219304Speter	default:
10319304Speter		abort();
10419304Speter		/* NOTREACHED */
10519304Speter	}
10619304Speter	return (0);
10719304Speter}
10819304Speter
10919304Speter/*
11019304Speter * cs_fspace --
11119304Speter *	If on a space, eat forward until something other than a
11219304Speter *	whitespace character.
11319304Speter *
11419304Speter * XXX
11519304Speter * Semantics of checking the current character were coded for the fword()
11619304Speter * function -- once the other word routines are converted, they may have
11719304Speter * to change.
11819304Speter *
119281373Sbapt * PUBLIC: int cs_fspace(SCR *, VCS *);
12019304Speter */
12119304Speterint
122254225Spetercs_fspace(SCR *sp, VCS *csp)
12319304Speter{
124254225Speter	if (csp->cs_flags != 0 || !ISBLANK(csp->cs_ch))
12519304Speter		return (0);
12619304Speter	for (;;) {
12719304Speter		if (cs_next(sp, csp))
12819304Speter			return (1);
129254225Speter		if (csp->cs_flags != 0 || !ISBLANK(csp->cs_ch))
13019304Speter			break;
13119304Speter	}
13219304Speter	return (0);
13319304Speter}
13419304Speter
13519304Speter/*
13619304Speter * cs_fblank --
13719304Speter *	Eat forward to the next non-whitespace character.
13819304Speter *
139281373Sbapt * PUBLIC: int cs_fblank(SCR *, VCS *);
14019304Speter */
14119304Speterint
142254225Spetercs_fblank(SCR *sp, VCS *csp)
14319304Speter{
14419304Speter	for (;;) {
14519304Speter		if (cs_next(sp, csp))
14619304Speter			return (1);
14719304Speter		if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
148254225Speter		    (csp->cs_flags == 0 && ISBLANK(csp->cs_ch)))
14919304Speter			continue;
15019304Speter		break;
15119304Speter	}
15219304Speter	return (0);
15319304Speter}
15419304Speter
15519304Speter/*
15619304Speter * cs_prev --
15719304Speter *	Retrieve the previous character.
15819304Speter *
159281373Sbapt * PUBLIC: int cs_prev(SCR *, VCS *);
16019304Speter */
16119304Speterint
162254225Spetercs_prev(SCR *sp, VCS *csp)
16319304Speter{
16419304Speter	switch (csp->cs_flags) {
16519304Speter	case CS_EMP:				/* EMP; get previous line. */
16619304Speter	case CS_EOL:				/* EOL; get previous line. */
16719304Speter		if (csp->cs_lno == 1) {		/* SOF. */
16819304Speter			csp->cs_flags = CS_SOF;
16919304Speter			break;
17019304Speter		}
17119304Speter		if (db_get(sp,			/* The line should exist. */
17219304Speter		    --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) {
17319304Speter			++csp->cs_lno;
17419304Speter			return (1);
17519304Speter		}
17619304Speter		if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
17719304Speter			csp->cs_cno = 0;
17819304Speter			csp->cs_flags = CS_EMP;
17919304Speter		} else {
18019304Speter			csp->cs_flags = 0;
18119304Speter			csp->cs_cno = csp->cs_len - 1;
18219304Speter			csp->cs_ch = csp->cs_bp[csp->cs_cno];
18319304Speter		}
18419304Speter		break;
18519304Speter	case CS_EOF:				/* EOF: get previous char. */
18619304Speter	case 0:
18719304Speter		if (csp->cs_cno == 0)
18819304Speter			if (csp->cs_lno == 1)
18919304Speter				csp->cs_flags = CS_SOF;
19019304Speter			else
19119304Speter				csp->cs_flags = CS_EOL;
19219304Speter		else
19319304Speter			csp->cs_ch = csp->cs_bp[--csp->cs_cno];
19419304Speter		break;
19519304Speter	case CS_SOF:				/* SOF. */
19619304Speter		break;
19719304Speter	default:
19819304Speter		abort();
19919304Speter		/* NOTREACHED */
20019304Speter	}
20119304Speter	return (0);
20219304Speter}
20319304Speter
20419304Speter/*
20519304Speter * cs_bblank --
20619304Speter *	Eat backward to the next non-whitespace character.
20719304Speter *
208281373Sbapt * PUBLIC: int cs_bblank(SCR *, VCS *);
20919304Speter */
21019304Speterint
211254225Spetercs_bblank(SCR *sp, VCS *csp)
21219304Speter{
21319304Speter	for (;;) {
21419304Speter		if (cs_prev(sp, csp))
21519304Speter			return (1);
21619304Speter		if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
217254225Speter		    (csp->cs_flags == 0 && ISBLANK(csp->cs_ch)))
21819304Speter			continue;
21919304Speter		break;
22019304Speter	}
22119304Speter	return (0);
22219304Speter}
223