xref: /minix/external/bsd/nvi/dist/vi/getc.c (revision 84d9c625)
1 /*	$NetBSD: getc.c,v 1.2 2013/11/22 15:52:06 christos Exp $ */
2 /*-
3  * Copyright (c) 1992, 1993, 1994
4  *	The Regents of the University of California.  All rights reserved.
5  * Copyright (c) 1992, 1993, 1994, 1995, 1996
6  *	Keith Bostic.  All rights reserved.
7  *
8  * See the LICENSE file for redistribution information.
9  */
10 
11 #include "config.h"
12 
13 #ifndef lint
14 static const char sccsid[] = "Id: getc.c,v 10.12 2001/06/25 15:19:30 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:30 ";
15 #endif /* not lint */
16 
17 #include <sys/types.h>
18 #include <sys/queue.h>
19 #include <sys/time.h>
20 
21 #include <bitstring.h>
22 #include <ctype.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 #include "../common/common.h"
28 #include "vi.h"
29 
30 /*
31  * Character stream routines --
32  *	These routines return the file a character at a time.  There are two
33  *	special cases.  First, the end of a line, end of a file, start of a
34  *	file and empty lines are returned as special cases, and no character
35  *	is returned.  Second, empty lines include lines that have only white
36  *	space in them, because the vi search functions don't care about white
37  *	space, and this makes it easier for them to be consistent.
38  */
39 
40 /*
41  * cs_init --
42  *	Initialize character stream routines.
43  *
44  * PUBLIC: int cs_init __P((SCR *, VCS *));
45  */
46 int
47 cs_init(SCR *sp, VCS *csp)
48 {
49 	int isempty;
50 
51 	if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) {
52 		if (isempty)
53 			msgq(sp, M_BERR, "177|Empty file");
54 		return (1);
55 	}
56 	if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
57 		csp->cs_cno = 0;
58 		csp->cs_flags = CS_EMP;
59 	} else {
60 		csp->cs_flags = 0;
61 		csp->cs_ch = csp->cs_bp[csp->cs_cno];
62 	}
63 	return (0);
64 }
65 
66 /*
67  * cs_next --
68  *	Retrieve the next character.
69  *
70  * PUBLIC: int cs_next __P((SCR *, VCS *));
71  */
72 int
73 cs_next(SCR *sp, VCS *csp)
74 {
75 	CHAR_T *p;
76 
77 	switch (csp->cs_flags) {
78 	case CS_EMP:				/* EMP; get next line. */
79 	case CS_EOL:				/* EOL; get next line. */
80 		if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) {
81 			--csp->cs_lno;
82 			csp->cs_flags = CS_EOF;
83 		} else {
84 			csp->cs_bp = p;
85 			if (csp->cs_len == 0 ||
86 			    v_isempty(csp->cs_bp, csp->cs_len)) {
87 				csp->cs_cno = 0;
88 				csp->cs_flags = CS_EMP;
89 			} else {
90 				csp->cs_flags = 0;
91 				csp->cs_ch = csp->cs_bp[csp->cs_cno = 0];
92 			}
93 		}
94 		break;
95 	case 0:
96 		if (csp->cs_cno == csp->cs_len - 1)
97 			csp->cs_flags = CS_EOL;
98 		else
99 			csp->cs_ch = csp->cs_bp[++csp->cs_cno];
100 		break;
101 	case CS_EOF:				/* EOF. */
102 		break;
103 	default:
104 		abort();
105 		/* NOTREACHED */
106 	}
107 	return (0);
108 }
109 
110 /*
111  * cs_fspace --
112  *	If on a space, eat forward until something other than a
113  *	whitespace character.
114  *
115  * XXX
116  * Semantics of checking the current character were coded for the fword()
117  * function -- once the other word routines are converted, they may have
118  * to change.
119  *
120  * PUBLIC: int cs_fspace __P((SCR *, VCS *));
121  */
122 int
123 cs_fspace(SCR *sp, VCS *csp)
124 {
125 	if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch))
126 		return (0);
127 	for (;;) {
128 		if (cs_next(sp, csp))
129 			return (1);
130 		if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch))
131 			break;
132 	}
133 	return (0);
134 }
135 
136 /*
137  * cs_fblank --
138  *	Eat forward to the next non-whitespace character.
139  *
140  * PUBLIC: int cs_fblank __P((SCR *, VCS *));
141  */
142 int
143 cs_fblank(SCR *sp, VCS *csp)
144 {
145 	for (;;) {
146 		if (cs_next(sp, csp))
147 			return (1);
148 		if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
149 		    (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch)))
150 			continue;
151 		break;
152 	}
153 	return (0);
154 }
155 
156 /*
157  * cs_prev --
158  *	Retrieve the previous character.
159  *
160  * PUBLIC: int cs_prev __P((SCR *, VCS *));
161  */
162 int
163 cs_prev(SCR *sp, VCS *csp)
164 {
165 	switch (csp->cs_flags) {
166 	case CS_EMP:				/* EMP; get previous line. */
167 	case CS_EOL:				/* EOL; get previous line. */
168 		if (csp->cs_lno == 1) {		/* SOF. */
169 			csp->cs_flags = CS_SOF;
170 			break;
171 		}
172 		if (db_get(sp,			/* The line should exist. */
173 		    --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) {
174 			++csp->cs_lno;
175 			return (1);
176 		}
177 		if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
178 			csp->cs_cno = 0;
179 			csp->cs_flags = CS_EMP;
180 		} else {
181 			csp->cs_flags = 0;
182 			csp->cs_cno = csp->cs_len - 1;
183 			csp->cs_ch = csp->cs_bp[csp->cs_cno];
184 		}
185 		break;
186 	case CS_EOF:				/* EOF: get previous char. */
187 	case 0:
188 		if (csp->cs_cno == 0)
189 			if (csp->cs_lno == 1)
190 				csp->cs_flags = CS_SOF;
191 			else
192 				csp->cs_flags = CS_EOL;
193 		else
194 			csp->cs_ch = csp->cs_bp[--csp->cs_cno];
195 		break;
196 	case CS_SOF:				/* SOF. */
197 		break;
198 	default:
199 		abort();
200 		/* NOTREACHED */
201 	}
202 	return (0);
203 }
204 
205 /*
206  * cs_bblank --
207  *	Eat backward to the next non-whitespace character.
208  *
209  * PUBLIC: int cs_bblank __P((SCR *, VCS *));
210  */
211 int
212 cs_bblank(SCR *sp, VCS *csp)
213 {
214 	for (;;) {
215 		if (cs_prev(sp, csp))
216 			return (1);
217 		if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
218 		    (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch)))
219 			continue;
220 		break;
221 	}
222 	return (0);
223 }
224