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