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