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