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 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 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 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 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 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 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