1 /* @(#)wwwrite.c 8.1 (Berkeley) 6/6/93 */ 2 /* $NetBSD: wwwrite.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Edward Wang at The University of California, Berkeley. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "ww.h" 37 #include "tt.h" 38 #include "xx.h" 39 #include "char.h" 40 41 #define UPDATE() \ 42 if (!ISSET(w->ww_wflags, WWW_NOUPDATE) && w->ww_cur.r >= 0 && \ 43 w->ww_cur.r < wwnrow && wwtouched[w->ww_cur.r]) \ 44 wwupdate1(w->ww_cur.r, w->ww_cur.r + 1) 45 46 /* 47 * To support control character expansion, we save the old 48 * p and q values in r and s, and point p at the beginning 49 * of the expanded string, and q at some safe place beyond it 50 * (p + 10). At strategic points in the loops, we check 51 * for (r && !*p) and restore the saved values back into 52 * p and q. Essentially, we implement a stack of depth 2, 53 * to avoid recursion, which might be a better idea. 54 */ 55 int 56 wwwrite(struct ww *w, const char *p, int n) 57 { 58 int hascursor; 59 const char *savep = p; 60 const char *q = p + n; 61 const char *r = NULL; 62 const char *s = NULL; 63 64 hascursor = ISSET(w->ww_wflags, WWW_HASCURSOR); 65 if (hascursor) 66 wwcursor(w, 0); 67 while (p < q && !ISSET(w->ww_pflags, WWP_STOPPED) && 68 (!wwinterrupt() || ISSET(w->ww_wflags, WWW_NOINTR))) { 69 if (r && !*p) { 70 p = r; 71 q = s; 72 r = NULL; 73 continue; 74 } 75 if (w->ww_wstate == 0 && 76 (isprt(*p) || 77 (ISSET(w->ww_wflags, WWW_UNCTRL) && isunctrl(*p)))) { 78 int i; 79 union ww_char *bp; 80 int col, col1; 81 82 if (ISSET(w->ww_wflags, WWW_INSERT)) { 83 /* this is very slow */ 84 if (*p == '\t') { 85 p++; 86 w->ww_cur.c += 8 - 87 ((w->ww_cur.c - w->ww_w.l) & 7); 88 goto chklf; 89 } 90 if (!isprt(*p)) { 91 r = p + 1; 92 s = q; 93 p = unctrl(*p); 94 q = p + 10; 95 } 96 wwinschar(w, w->ww_cur.r, w->ww_cur.c, 97 *p++, w->ww_modes); 98 goto right; 99 } 100 101 bp = &w->ww_buf[w->ww_cur.r][w->ww_cur.c]; 102 i = w->ww_cur.c; 103 while (i < w->ww_w.r && p < q) 104 if (!*p && r) { 105 p = r; 106 q = s; 107 r = NULL; 108 } else if (*p == '\t') { 109 int tmp = 8 - ((i - w->ww_w.l) & 7); 110 p++; 111 i += tmp; 112 bp += tmp; 113 } else if (isprt(*p)) { 114 bp++->c_w = *p++ 115 | w->ww_modes << WWC_MSHIFT; 116 i++; 117 } else if (ISSET(w->ww_wflags, WWW_UNCTRL) && 118 isunctrl(*p)) { 119 r = p + 1; 120 s = q; 121 p = unctrl(*p); 122 q = p + 10; 123 } else 124 break; 125 col = MAX(w->ww_cur.c, w->ww_i.l); 126 col1 = MIN(i, w->ww_i.r); 127 w->ww_cur.c = i; 128 if (w->ww_cur.r >= w->ww_i.t 129 && w->ww_cur.r < w->ww_i.b) { 130 union ww_char *ns = wwns[w->ww_cur.r]; 131 unsigned char *smap = 132 &wwsmap[w->ww_cur.r][col]; 133 char *win = w->ww_win[w->ww_cur.r]; 134 int nchanged = 0; 135 136 bp = w->ww_buf[w->ww_cur.r]; 137 for (i = col; i < col1; i++) 138 if (*smap++ == w->ww_index) { 139 nchanged++; 140 ns[i].c_w = bp[i].c_w 141 ^ win[i] << WWC_MSHIFT; 142 } 143 if (nchanged > 0) 144 wwtouched[w->ww_cur.r] |= WWU_TOUCHED; 145 } 146 chklf: 147 if (w->ww_cur.c >= w->ww_w.r) 148 goto crlf; 149 } else switch (w->ww_wstate) { 150 case 0: 151 switch (*p++) { 152 case '\n': 153 if (ISSET(w->ww_wflags, WWW_MAPNL)) 154 crlf: 155 w->ww_cur.c = w->ww_w.l; 156 lf: 157 UPDATE(); 158 if (++w->ww_cur.r >= w->ww_w.b) { 159 w->ww_cur.r = w->ww_w.b - 1; 160 if (w->ww_w.b < w->ww_b.b) { 161 (void) wwscroll1(w, w->ww_i.t, 162 w->ww_i.b, 1, 0); 163 w->ww_buf++; 164 w->ww_b.t--; 165 w->ww_b.b--; 166 } else 167 wwdelline(w, w->ww_b.t); 168 } 169 break; 170 case '\b': 171 if (--w->ww_cur.c < w->ww_w.l) { 172 w->ww_cur.c = w->ww_w.r - 1; 173 goto up; 174 } 175 break; 176 case '\r': 177 w->ww_cur.c = w->ww_w.l; 178 break; 179 case ctrl('g'): 180 ttputc(ctrl('g')); 181 break; 182 case ctrl('['): 183 w->ww_wstate = 1; 184 break; 185 } 186 break; 187 case 1: 188 w->ww_wstate = 0; 189 switch (*p++) { 190 case '@': 191 SET(w->ww_wflags, WWW_INSERT); 192 break; 193 case 'A': 194 up: 195 UPDATE(); 196 if (--w->ww_cur.r < w->ww_w.t) { 197 w->ww_cur.r = w->ww_w.t; 198 if (w->ww_w.t > w->ww_b.t) { 199 (void) wwscroll1(w, w->ww_i.t, 200 w->ww_i.b, -1, 0); 201 w->ww_buf--; 202 w->ww_b.t++; 203 w->ww_b.b++; 204 } else 205 wwinsline(w, w->ww_b.t); 206 } 207 break; 208 case 'B': 209 goto lf; 210 case 'C': 211 right: 212 w->ww_cur.c++; 213 goto chklf; 214 case 'E': 215 w->ww_buf -= w->ww_w.t - w->ww_b.t; 216 w->ww_b.t = w->ww_w.t; 217 w->ww_b.b = w->ww_b.t + w->ww_b.nr; 218 w->ww_cur.r = w->ww_w.t; 219 w->ww_cur.c = w->ww_w.l; 220 wwclreos(w, w->ww_w.t, w->ww_w.l); 221 break; 222 case 'H': 223 UPDATE(); 224 w->ww_cur.r = w->ww_w.t; 225 w->ww_cur.c = w->ww_w.l; 226 break; 227 case 'J': 228 wwclreos(w, w->ww_cur.r, w->ww_cur.c); 229 break; 230 case 'K': 231 wwclreol(w, w->ww_cur.r, w->ww_cur.c); 232 break; 233 case 'L': 234 UPDATE(); 235 wwinsline(w, w->ww_cur.r); 236 break; 237 case 'M': 238 wwdelline(w, w->ww_cur.r); 239 break; 240 case 'N': 241 wwdelchar(w, w->ww_cur.r, w->ww_cur.c); 242 break; 243 case 'O': 244 CLR(w->ww_wflags, WWW_INSERT); 245 break; 246 case 'P': 247 wwinschar(w, w->ww_cur.r, w->ww_cur.c, ' ', 0); 248 break; 249 case 'X': 250 wwupdate(); 251 break; 252 case 'Y': 253 UPDATE(); 254 w->ww_wstate = 2; 255 break; 256 case 'Z': 257 wwupdate(); 258 xxflush(0); 259 break; 260 case 's': 261 w->ww_wstate = 4; 262 break; 263 case 'r': 264 w->ww_wstate = 5; 265 break; 266 } 267 break; 268 case 2: 269 w->ww_cur.r = w->ww_w.t + 270 (unsigned)(*p++ - ' ') % w->ww_w.nr; 271 w->ww_wstate = 3; 272 break; 273 case 3: 274 w->ww_cur.c = w->ww_w.l + 275 (unsigned)(*p++ - ' ') % w->ww_w.nc; 276 w->ww_wstate = 0; 277 break; 278 case 4: 279 w->ww_modes |= *p++ & wwavailmodes; 280 w->ww_wstate = 0; 281 break; 282 case 5: 283 w->ww_modes &= ~*p++; 284 w->ww_wstate = 0; 285 break; 286 } 287 } 288 if (hascursor) 289 wwcursor(w, 1); 290 wwnwwr++; 291 wwnwwra += n; 292 n = p - savep; 293 wwnwwrc += n; 294 return n; 295 } 296