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