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