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(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(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(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(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(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(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 } 223