1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Wang at The University of California, Berkeley. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)wwwrite.c 8.1 (Berkeley) 06/06/93"; 13 #endif /* not lint */ 14 15 #include "ww.h" 16 #include "tt.h" 17 #include "char.h" 18 19 #define UPDATE() \ 20 if (!w->ww_noupdate && w->ww_cur.r >= 0 && w->ww_cur.r < wwnrow && \ 21 wwtouched[w->ww_cur.r]) \ 22 wwupdate1(w->ww_cur.r, w->ww_cur.r + 1) 23 24 /* 25 * To support control character expansion, we save the old 26 * p and q values in r and s, and point p at the beginning 27 * of the expanded string, and q at some safe place beyond it 28 * (p + 10). At strategic points in the loops, we check 29 * for (r && !*p) and restore the saved values back into 30 * p and q. Essentially, we implement a stack of depth 2, 31 * to avoid recursion, which might be a better idea. 32 */ 33 wwwrite(w, p, n) 34 register struct ww *w; 35 register char *p; 36 int n; 37 { 38 char hascursor; 39 char *savep = p; 40 char *q = p + n; 41 char *r = 0; 42 char *s; 43 44 #ifdef lint 45 s = 0; /* define it before possible use */ 46 #endif 47 if (hascursor = w->ww_hascursor) 48 wwcursor(w, 0); 49 while (p < q && !w->ww_stopped && (!wwinterrupt() || w->ww_nointr)) { 50 if (r && !*p) { 51 p = r; 52 q = s; 53 r = 0; 54 continue; 55 } 56 if (w->ww_wstate == 0 && 57 (isprt(*p) || w->ww_unctrl && isunctrl(*p))) { 58 register i; 59 register union ww_char *bp; 60 int col, col1; 61 62 if (w->ww_insert) { /* this is very slow */ 63 if (*p == '\t') { 64 p++; 65 w->ww_cur.c += 8 - 66 (w->ww_cur.c - w->ww_w.l & 7); 67 goto chklf; 68 } 69 if (!isprt(*p)) { 70 r = p + 1; 71 s = q; 72 p = unctrl(*p); 73 q = p + 10; 74 } 75 wwinschar(w, w->ww_cur.r, w->ww_cur.c, 76 *p++, w->ww_modes); 77 goto right; 78 } 79 80 bp = &w->ww_buf[w->ww_cur.r][w->ww_cur.c]; 81 i = w->ww_cur.c; 82 while (i < w->ww_w.r && p < q) 83 if (!*p && r) { 84 p = r; 85 q = s; 86 r = 0; 87 } else if (*p == '\t') { 88 register tmp = 8 - (i - w->ww_w.l & 7); 89 p++; 90 i += tmp; 91 bp += tmp; 92 } else if (isprt(*p)) { 93 bp++->c_w = *p++ 94 | w->ww_modes << WWC_MSHIFT; 95 i++; 96 } else if (w->ww_unctrl && isunctrl(*p)) { 97 r = p + 1; 98 s = q; 99 p = unctrl(*p); 100 q = p + 10; 101 } else 102 break; 103 col = MAX(w->ww_cur.c, w->ww_i.l); 104 col1 = MIN(i, w->ww_i.r); 105 w->ww_cur.c = i; 106 if (w->ww_cur.r >= w->ww_i.t 107 && w->ww_cur.r < w->ww_i.b) { 108 register union ww_char *ns = wwns[w->ww_cur.r]; 109 register char *smap = &wwsmap[w->ww_cur.r][col]; 110 register char *win = w->ww_win[w->ww_cur.r]; 111 int nchanged = 0; 112 113 bp = w->ww_buf[w->ww_cur.r]; 114 for (i = col; i < col1; i++) 115 if (*smap++ == w->ww_index) { 116 nchanged++; 117 ns[i].c_w = bp[i].c_w 118 ^ win[i] << WWC_MSHIFT; 119 } 120 if (nchanged > 0) 121 wwtouched[w->ww_cur.r] |= WWU_TOUCHED; 122 } 123 chklf: 124 if (w->ww_cur.c >= w->ww_w.r) 125 goto crlf; 126 } else switch (w->ww_wstate) { 127 case 0: 128 switch (*p++) { 129 case '\n': 130 if (w->ww_mapnl) 131 crlf: 132 w->ww_cur.c = w->ww_w.l; 133 lf: 134 UPDATE(); 135 if (++w->ww_cur.r >= w->ww_w.b) { 136 w->ww_cur.r = w->ww_w.b - 1; 137 if (w->ww_w.b < w->ww_b.b) { 138 (void) wwscroll1(w, w->ww_i.t, 139 w->ww_i.b, 1, 0); 140 w->ww_buf++; 141 w->ww_b.t--; 142 w->ww_b.b--; 143 } else 144 wwdelline(w, w->ww_b.t); 145 } 146 break; 147 case '\b': 148 if (--w->ww_cur.c < w->ww_w.l) { 149 w->ww_cur.c = w->ww_w.r - 1; 150 goto up; 151 } 152 break; 153 case '\r': 154 w->ww_cur.c = w->ww_w.l; 155 break; 156 case ctrl('g'): 157 ttputc(ctrl('g')); 158 break; 159 case ctrl('['): 160 w->ww_wstate = 1; 161 break; 162 } 163 break; 164 case 1: 165 w->ww_wstate = 0; 166 switch (*p++) { 167 case '@': 168 w->ww_insert = 1; 169 break; 170 case 'A': 171 up: 172 UPDATE(); 173 if (--w->ww_cur.r < w->ww_w.t) { 174 w->ww_cur.r = w->ww_w.t; 175 if (w->ww_w.t > w->ww_b.t) { 176 (void) wwscroll1(w, w->ww_i.t, 177 w->ww_i.b, -1, 0); 178 w->ww_buf--; 179 w->ww_b.t++; 180 w->ww_b.b++; 181 } else 182 wwinsline(w, w->ww_b.t); 183 } 184 break; 185 case 'B': 186 goto lf; 187 case 'C': 188 right: 189 w->ww_cur.c++; 190 goto chklf; 191 case 'E': 192 w->ww_buf -= w->ww_w.t - w->ww_b.t; 193 w->ww_b.t = w->ww_w.t; 194 w->ww_b.b = w->ww_b.t + w->ww_b.nr; 195 w->ww_cur.r = w->ww_w.t; 196 w->ww_cur.c = w->ww_w.l; 197 wwclreos(w, w->ww_w.t, w->ww_w.l); 198 break; 199 case 'H': 200 UPDATE(); 201 w->ww_cur.r = w->ww_w.t; 202 w->ww_cur.c = w->ww_w.l; 203 break; 204 case 'J': 205 wwclreos(w, w->ww_cur.r, w->ww_cur.c); 206 break; 207 case 'K': 208 wwclreol(w, w->ww_cur.r, w->ww_cur.c); 209 break; 210 case 'L': 211 UPDATE(); 212 wwinsline(w, w->ww_cur.r); 213 break; 214 case 'M': 215 wwdelline(w, w->ww_cur.r); 216 break; 217 case 'N': 218 wwdelchar(w, w->ww_cur.r, w->ww_cur.c); 219 break; 220 case 'O': 221 w->ww_insert = 0; 222 break; 223 case 'P': 224 wwinschar(w, w->ww_cur.r, w->ww_cur.c, ' ', 0); 225 break; 226 case 'X': 227 wwupdate(); 228 break; 229 case 'Y': 230 UPDATE(); 231 w->ww_wstate = 2; 232 break; 233 case 'Z': 234 wwupdate(); 235 xxflush(0); 236 break; 237 case 's': 238 w->ww_wstate = 4; 239 break; 240 case 'r': 241 w->ww_wstate = 5; 242 break; 243 } 244 break; 245 case 2: 246 w->ww_cur.r = w->ww_w.t + 247 (unsigned)(*p++ - ' ') % w->ww_w.nr; 248 w->ww_wstate = 3; 249 break; 250 case 3: 251 w->ww_cur.c = w->ww_w.l + 252 (unsigned)(*p++ - ' ') % w->ww_w.nc; 253 w->ww_wstate = 0; 254 break; 255 case 4: 256 w->ww_modes |= *p++ & wwavailmodes; 257 w->ww_wstate = 0; 258 break; 259 case 5: 260 w->ww_modes &= ~*p++; 261 w->ww_wstate = 0; 262 break; 263 } 264 } 265 if (hascursor) 266 wwcursor(w, 1); 267 wwnwwr++; 268 wwnwwra += n; 269 n = p - savep; 270 wwnwwrc += n; 271 return n; 272 } 273