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[] = "@(#)getc.c 10.10 (Berkeley) 3/6/96"; 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(sp, csp) 47 SCR *sp; 48 VCS *csp; 49 { 50 int isempty; 51 52 if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) { 53 if (isempty) 54 msgq(sp, M_BERR, "177|Empty file"); 55 return (1); 56 } 57 if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { 58 csp->cs_cno = 0; 59 csp->cs_flags = CS_EMP; 60 } else { 61 csp->cs_flags = 0; 62 csp->cs_ch = csp->cs_bp[csp->cs_cno]; 63 } 64 return (0); 65 } 66 67 /* 68 * cs_next -- 69 * Retrieve the next character. 70 * 71 * PUBLIC: int cs_next __P((SCR *, VCS *)); 72 */ 73 int 74 cs_next(sp, csp) 75 SCR *sp; 76 VCS *csp; 77 { 78 char *p; 79 80 switch (csp->cs_flags) { 81 case CS_EMP: /* EMP; get next line. */ 82 case CS_EOL: /* EOL; get next line. */ 83 if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) { 84 --csp->cs_lno; 85 csp->cs_flags = CS_EOF; 86 } else { 87 csp->cs_bp = p; 88 if (csp->cs_len == 0 || 89 v_isempty(csp->cs_bp, csp->cs_len)) { 90 csp->cs_cno = 0; 91 csp->cs_flags = CS_EMP; 92 } else { 93 csp->cs_flags = 0; 94 csp->cs_ch = csp->cs_bp[csp->cs_cno = 0]; 95 } 96 } 97 break; 98 case 0: 99 if (csp->cs_cno == csp->cs_len - 1) 100 csp->cs_flags = CS_EOL; 101 else 102 csp->cs_ch = csp->cs_bp[++csp->cs_cno]; 103 break; 104 case CS_EOF: /* EOF. */ 105 break; 106 default: 107 abort(); 108 /* NOTREACHED */ 109 } 110 return (0); 111 } 112 113 /* 114 * cs_fspace -- 115 * If on a space, eat forward until something other than a 116 * whitespace character. 117 * 118 * XXX 119 * Semantics of checking the current character were coded for the fword() 120 * function -- once the other word routines are converted, they may have 121 * to change. 122 * 123 * PUBLIC: int cs_fspace __P((SCR *, VCS *)); 124 */ 125 int 126 cs_fspace(sp, csp) 127 SCR *sp; 128 VCS *csp; 129 { 130 if (csp->cs_flags != 0 || !isblank(csp->cs_ch)) 131 return (0); 132 for (;;) { 133 if (cs_next(sp, csp)) 134 return (1); 135 if (csp->cs_flags != 0 || !isblank(csp->cs_ch)) 136 break; 137 } 138 return (0); 139 } 140 141 /* 142 * cs_fblank -- 143 * Eat forward to the next non-whitespace character. 144 * 145 * PUBLIC: int cs_fblank __P((SCR *, VCS *)); 146 */ 147 int 148 cs_fblank(sp, csp) 149 SCR *sp; 150 VCS *csp; 151 { 152 for (;;) { 153 if (cs_next(sp, csp)) 154 return (1); 155 if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP || 156 csp->cs_flags == 0 && isblank(csp->cs_ch)) 157 continue; 158 break; 159 } 160 return (0); 161 } 162 163 /* 164 * cs_prev -- 165 * Retrieve the previous character. 166 * 167 * PUBLIC: int cs_prev __P((SCR *, VCS *)); 168 */ 169 int 170 cs_prev(sp, csp) 171 SCR *sp; 172 VCS *csp; 173 { 174 switch (csp->cs_flags) { 175 case CS_EMP: /* EMP; get previous line. */ 176 case CS_EOL: /* EOL; get previous line. */ 177 if (csp->cs_lno == 1) { /* SOF. */ 178 csp->cs_flags = CS_SOF; 179 break; 180 } 181 if (db_get(sp, /* The line should exist. */ 182 --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) { 183 ++csp->cs_lno; 184 return (1); 185 } 186 if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { 187 csp->cs_cno = 0; 188 csp->cs_flags = CS_EMP; 189 } else { 190 csp->cs_flags = 0; 191 csp->cs_cno = csp->cs_len - 1; 192 csp->cs_ch = csp->cs_bp[csp->cs_cno]; 193 } 194 break; 195 case CS_EOF: /* EOF: get previous char. */ 196 case 0: 197 if (csp->cs_cno == 0) 198 if (csp->cs_lno == 1) 199 csp->cs_flags = CS_SOF; 200 else 201 csp->cs_flags = CS_EOL; 202 else 203 csp->cs_ch = csp->cs_bp[--csp->cs_cno]; 204 break; 205 case CS_SOF: /* SOF. */ 206 break; 207 default: 208 abort(); 209 /* NOTREACHED */ 210 } 211 return (0); 212 } 213 214 /* 215 * cs_bblank -- 216 * Eat backward to the next non-whitespace character. 217 * 218 * PUBLIC: int cs_bblank __P((SCR *, VCS *)); 219 */ 220 int 221 cs_bblank(sp, csp) 222 SCR *sp; 223 VCS *csp; 224 { 225 for (;;) { 226 if (cs_prev(sp, csp)) 227 return (1); 228 if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP || 229 csp->cs_flags == 0 && isblank(csp->cs_ch)) 230 continue; 231 break; 232 } 233 return (0); 234 } 235