1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 30 /* Copyright (c) 1981 Regents of the University of California */ 31 32 #include "ex.h" 33 #include "ex_temp.h" 34 #include "ex_tty.h" 35 36 /* 37 * Set command. 38 */ 39 unsigned char optname[ONMSZ]; 40 41 void 42 set(void) 43 { 44 unsigned char *cp; 45 struct option *op; 46 int c; 47 bool no; 48 extern short ospeed; 49 #ifdef TRACE 50 int k, label; 51 line *tmpadr; 52 #endif 53 54 setnoaddr(); 55 if (skipend()) { 56 if (peekchar() != EOF) 57 ignchar(); 58 propts(); 59 return; 60 } 61 do { 62 cp = optname; 63 do { 64 if (cp < &optname[ONMSZ - 2]) 65 *cp++ = getchar(); 66 } while (isalnum(peekchar())); 67 *cp = 0; 68 cp = optname; 69 if (eq("all", cp)) { 70 if (inopen) 71 pofix(); 72 prall(); 73 goto next; 74 } 75 no = 0; 76 #ifdef TRACE 77 /* 78 * General purpose test code for looking at address of those 79 * invisible marks (as well as the visible ones). 80 */ 81 if (eq("marks", cp)) { 82 viprintf("Marks Address\n\r"); 83 viprintf(" \n"); 84 viprintf("\n"); 85 for (k = 0; k <= 25; k++) 86 viprintf("Mark:%c\t%d\n", k+'a', names[k]); 87 goto next; 88 } 89 90 /* 91 * General purpose test code for looking at 92 * named registers. 93 */ 94 95 if (eq("named",cp)) { 96 if (inopen) 97 pofix(); 98 shownam(); 99 goto next; 100 } 101 102 /* 103 * General purpose test code for looking at 104 * numbered registers. 105 */ 106 107 if (eq("nbrreg",cp)) { 108 if (inopen) 109 pofix(); 110 shownbr(); 111 goto next; 112 } 113 114 /* 115 * General purpose test code for looking at addresses 116 * in the edit and save areas of VI. 117 */ 118 119 if (eq("buffers",cp)) { 120 if (inopen) 121 pofix(); 122 viprintf("\nLabels Address Contents\n"); 123 viprintf("====== ======= ========"); 124 for (tmpadr = zero; tmpadr <= dol; tmpadr++) { 125 label =0; 126 if (tmpadr == zero) { 127 viprintf("ZERO:\t"); 128 label = 2; 129 } 130 if (tmpadr == one) { 131 if (label > 0) 132 viprintf("\nONE:\t"); 133 else 134 viprintf("ONE:\t"); 135 label = 1; 136 } 137 if (tmpadr == dot) { 138 if (label > 0) 139 viprintf("\nDOT:\t"); 140 else 141 viprintf("DOT:\t"); 142 label = 1; 143 } 144 if (tmpadr == undap1) { 145 if (label > 0) 146 viprintf("\nUNDAP1:\t"); 147 else 148 viprintf("UNDAP1:\t"); 149 label = 1; 150 } 151 if (tmpadr == undap2) { 152 if (label > 0) 153 viprintf("\nUNDAP2:\t"); 154 else 155 viprintf("UNDAP2:\t"); 156 label = 1; 157 } 158 if (tmpadr == unddel) { 159 if (label > 0) 160 viprintf("\nUNDDEL:\t"); 161 else 162 viprintf("UNDDEL:\t"); 163 label = 1; 164 } 165 if (tmpadr == dol) { 166 if (label > 0) 167 viprintf("\nDOL:\t"); 168 else 169 viprintf("DOL:\t"); 170 label = 1; 171 } 172 for (k=0; k<=25; k++) 173 if (names[k] == (*tmpadr &~ 01)) { 174 if (label > 0) 175 viprintf( 176 "\nMark:%c\t%d\t", k+'a', names[k]); 177 else 178 viprintf( 179 "Mark:%c\t%d\t", k+'a', names[k]); 180 label=1; 181 } 182 if (label == 0) 183 continue; 184 185 if (label == 2) 186 viprintf("%d\n", tmpadr); 187 else { 188 viprintf("%d\t", tmpadr); 189 getaline(*tmpadr); 190 pline(lineno(tmpadr)); 191 putchar('\n'); 192 } 193 } 194 195 for (tmpadr = dol+1; tmpadr <= unddol; tmpadr++) { 196 label =0; 197 if (tmpadr == dol+1) { 198 viprintf("DOL+1:\t"); 199 label = 1; 200 } 201 if (tmpadr == unddel) { 202 if (label > 0) 203 viprintf("\nUNDDEL:\t"); 204 else 205 viprintf("UNDDEL:\t"); 206 label = 1; 207 } 208 if (tmpadr == unddol) { 209 if (label > 0) 210 viprintf("\nUNDDOL:\t"); 211 else 212 viprintf("UNDDOL:\t"); 213 label = 1; 214 } 215 for (k=0; k<=25; k++) 216 if (names[k] == (*tmpadr &~ 01)) { 217 if (label > 0) 218 viprintf( 219 "\nMark:%c\t%d\t", k+'a', names[k]); 220 else 221 viprintf( 222 "Mark:%c\t%d\t", k+'a', names[k]); 223 label=1; 224 } 225 if (label == 0) 226 continue; 227 if (label == 2) 228 viprintf("%d\n", tmpadr); 229 else { 230 viprintf("%d\t", tmpadr); 231 getaline(*tmpadr); 232 pline(lineno(tmpadr)); 233 putchar('\n'); 234 } 235 } 236 goto next; 237 } 238 #endif 239 if (cp[0] == 'n' && cp[1] == 'o' && cp[2] != 'v') { 240 cp += 2; 241 no++; 242 } 243 /* Implement w300, w1200, and w9600 specially */ 244 if (eq(cp, "w300")) { 245 if (ospeed >= B1200) { 246 dontset: 247 (void)getchar(); /* = */ 248 (void)getnum(); /* value */ 249 continue; 250 } 251 cp = (unsigned char *)"window"; 252 } else if (eq(cp, "w1200")) { 253 if (ospeed < B1200 || ospeed >= B2400) 254 goto dontset; 255 cp = (unsigned char *)"window"; 256 } else if (eq(cp, "w9600")) { 257 if (ospeed < B2400) 258 goto dontset; 259 cp = (unsigned char *)"window"; 260 } 261 for (op = options; op < &options[vi_NOPTS]; op++) 262 if (eq(op->oname, cp) || op->oabbrev && eq(op->oabbrev, cp)) 263 break; 264 if (op->oname == 0) 265 serror(value(vi_TERSE) ? (unsigned char *) 266 gettext("%s: No such option") : 267 (unsigned char *) 268 gettext("%s: No such option - 'set all' gives all option values"), cp); 269 c = skipwh(); 270 if (peekchar() == '?') { 271 ignchar(); 272 printone: 273 propt(op); 274 noonl(); 275 goto next; 276 } 277 if (op->otype == ONOFF) { 278 op->ovalue = 1 - no; 279 if (op == &options[vi_PROMPT]) 280 oprompt = 1 - no; 281 goto next; 282 } 283 if (no) 284 serror((unsigned char *) 285 gettext("Option %s is not a toggle"), op->oname); 286 if (c != 0 || setend()) 287 goto printone; 288 if (getchar() != '=') 289 serror(value(vi_TERSE) ? (unsigned char *) 290 gettext("Missing =") : 291 (unsigned char *) 292 gettext("Missing = in assignment to option %s"), 293 op->oname); 294 switch (op->otype) { 295 296 case NUMERIC: 297 if (!isdigit(peekchar())) 298 error(value(vi_TERSE) ? 299 gettext("Digits required") : gettext("Digits required after =")); 300 op->ovalue = getnum(); 301 if (value(vi_TABSTOP) <= 0) 302 value(vi_TABSTOP) = TABS; 303 if (op == &options[vi_WINDOW]) { 304 if (value(vi_WINDOW) >= lines) 305 value(vi_WINDOW) = lines-1; 306 vsetsiz(value(vi_WINDOW)); 307 } 308 break; 309 310 case STRING: 311 case OTERM: 312 cp = optname; 313 while (!setend()) { 314 if (cp >= &optname[ONMSZ]) 315 error(value(vi_TERSE) ? 316 gettext("String too long") : gettext("String too long in option assignment")); 317 /* adb change: allow whitepace in strings */ 318 if( (*cp = getchar()) == '\\') 319 if( peekchar() != EOF) 320 *cp = getchar(); 321 cp++; 322 } 323 *cp = 0; 324 if (op->otype == OTERM) { 325 /* 326 * At first glance it seems like we shouldn't care if the terminal type 327 * is changed inside visual mode, as long as we assume the screen is 328 * a mess and redraw it. However, it's a much harder problem than that. 329 * If you happen to change from 1 crt to another that both have the same 330 * size screen, it's OK. But if the screen size if different, the stuff 331 * that gets initialized in vop() will be wrong. This could be overcome 332 * by redoing the initialization, e.g. making the first 90% of vop into 333 * a subroutine. However, the most useful case is where you forgot to do 334 * a setenv before you went into the editor and it thinks you're on a dumb 335 * terminal. Ex treats this like hardcopy and goes into HARDOPEN mode. 336 * This loses because the first part of vop calls oop in this case. 337 */ 338 if (inopen) 339 error(gettext("Can't change type of terminal from within open/visual")); 340 unterm(); 341 setterm(optname); 342 } else { 343 CP(op->osvalue, optname); 344 op->odefault = 1; 345 } 346 break; 347 } 348 next: 349 flush(); 350 } while (!skipend()); 351 eol(); 352 } 353 354 void 355 unterm(void) 356 { 357 /* 358 * All terminal mapped statements must be deleted. 359 * All user-defined mapped statements, cap=descr, 360 * are left unchanged. 361 */ 362 363 int i; 364 365 for (i=0; i < MAXNOMACS; i++) { 366 367 /* 368 * Unmap any terminal-defined arrow keys 369 */ 370 371 if (arrows[i].cap && arrows[i].descr && 372 strcmp(arrows[i].cap, arrows[i].descr)) 373 addmac(arrows[i].cap, NOSTR, NOSTR, arrows); 374 375 /* 376 * Unmap any terminal-defined function keys 377 */ 378 379 if (immacs[i].cap && immacs[i].descr && strcmp(immacs[i].cap, immacs[i].descr)) 380 addmac(immacs[i].cap, NOSTR, NOSTR, immacs); 381 382 } 383 } 384 385 386 int 387 setend(void) 388 { 389 390 return (iswhite(peekchar()) || endcmd(peekchar())); 391 } 392 393 void 394 prall(void) 395 { 396 int incr = (vi_NOPTS + 2) / 3; 397 int rows = incr; 398 struct option *op = options; 399 400 for (; rows; rows--, op++) { 401 propt(op); 402 gotab(24); 403 propt(&op[incr]); 404 if (&op[2*incr] < &options[vi_NOPTS]) { 405 gotab(56); 406 propt(&op[2 * incr]); 407 } 408 putNFL(); 409 } 410 } 411 412 void 413 propts(void) 414 { 415 struct option *op; 416 417 for (op = options; op < &options[vi_NOPTS]; op++) { 418 if (op == &options[vi_TTYTYPE]) 419 continue; 420 switch (op->otype) { 421 422 case ONOFF: 423 case NUMERIC: 424 if (op->ovalue == op->odefault) 425 continue; 426 break; 427 428 case STRING: 429 if (op->odefault == 0) 430 continue; 431 break; 432 } 433 propt(op); 434 putchar(' '); 435 } 436 noonl(); 437 flush(); 438 } 439 440 void 441 propt(struct option *op) 442 { 443 unsigned char *name; 444 445 name = (unsigned char *)op->oname; 446 447 switch (op->otype) { 448 449 case ONOFF: 450 viprintf("%s%s", op->ovalue ? "" : "no", name); 451 break; 452 453 case NUMERIC: 454 viprintf("%s=%d", name, op->ovalue); 455 break; 456 457 case STRING: 458 case OTERM: 459 viprintf("%s=%s", name, op->osvalue); 460 break; 461 } 462 } 463