|
|
1.1 root 1: /* opts.c */
2:
3: /* Author:
4: * Steve Kirkendall
5: * 14407 SW Teal Blvd. #C
6: * Beaverton, OR 97005
7: * [email protected]
8: */
9:
10:
11: /* This file contains the code that manages the run-time options -- The
12: * values that can be modified via the "set" command.
13: */
14:
15: #include "config.h"
16: #include "vi.h"
17: #include "ctype.h"
18: #ifndef NULL
19: #define NULL (char *)0
20: #endif
21: extern char *getenv();
22:
23: /* maximum width to permit for strings, including ="" */
24: #define MAXWIDTH 20
25:
26: /* These are the default values of all options */
27: char o_autoindent[1] = {FALSE};
28: char o_autoprint[1] = {TRUE};
29: char o_autotab[1] = {TRUE};
30: char o_autowrite[1] = {FALSE};
31: char o_columns[3] = {80, 32, 255};
32: char o_directory[30] = TMPDIR;
33: char o_edcompatible[1] = {FALSE};
34: char o_equalprg[80] = {"fmt"};
35: char o_errorbells[1] = {TRUE};
36: char o_exrefresh[1] = {TRUE};
37: char o_ignorecase[1] = {FALSE};
38: char o_keytime[3] = {2, 0, 50};
39: char o_keywordprg[80] = {KEYWORDPRG};
40: char o_lines[3] = {25, 2, 96};
41: char o_list[1] = {FALSE};
42: char o_number[1] = {FALSE};
43: char o_readonly[1] = {FALSE};
44: char o_remap[1] = {TRUE};
45: char o_report[3] = {5, 1, 127};
46: char o_scroll[3] = {12, 1, 127};
47: char o_shell[60] = SHELL;
48: char o_shiftwidth[3] = {8, 1, 255};
49: char o_sidescroll[3] = {8, 1, 40};
50: char o_sync[1] = {NEEDSYNC};
51: char o_tabstop[3] = {8, 1, 40};
52: char o_term[30] = "?";
53: char o_flash[1] = {TRUE};
54: char o_warn[1] = {TRUE};
55: char o_wrapscan[1] = {TRUE};
56:
57: #ifndef CRUNCH
58: char o_beautify[1] = {FALSE};
59: char o_exrc[1] = {FALSE};
60: char o_mesg[1] = {TRUE};
61: char o_more[1] = {TRUE};
62: char o_nearscroll[3] = {15, 0, 255};
63: char o_novice[1] = {FALSE};
64: char o_prompt[1] = {TRUE};
65: char o_taglength[3] = {0, 0, 30};
66: char o_terse[1] = {FALSE};
67: char o_window[3] = {0, 1, 24};
68: char o_wrapmargin[3] = {0, 0, 255};
69: char o_writeany[1] = {FALSE};
70: #endif
71:
72: #ifndef NO_ERRLIST
73: char o_cc[30] = {CC_COMMAND};
74: char o_make[30] = {MAKE_COMMAND};
75: #endif
76:
77: #ifndef NO_CHARATTR
78: char o_charattr[1] = {FALSE};
79: #endif
80:
81: #ifndef NO_DIGRAPH
82: char o_digraph[1] = {FALSE};
83: char o_flipcase[80]
84: # ifdef CS_IBMPC
85: = {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"}
86: # endif
87: # ifdef CS_LATIN1
88: /* initialized by initopts() */
89: # endif
90: ;
91: #endif
92:
93: #ifndef NO_SENTENCE
94: char o_hideformat[1] = {FALSE};
95: #endif
96:
97: #ifndef NO_EXTENSIONS
98: char o_inputmode[1] = {FALSE};
99: char o_ruler[1] = {FALSE};
100: #endif
101:
102: #ifndef NO_MAGIC
103: char o_magic[1] = {TRUE};
104: #endif
105:
106: #ifndef NO_MODELINES
107: char o_modelines[1] = {FALSE};
108: #endif
109:
110: #ifndef NO_SENTENCE
111: char o_paragraphs[30] = "PPppIPLPQP";
112: char o_sections[30] = "NHSHSSSEse";
113: #endif
114:
115: #if MSDOS
116: char o_pcbios[1] = {TRUE};
117: #endif
118:
119: #ifndef NO_SHOWMATCH
120: char o_showmatch[1] = {FALSE};
121: #endif
122:
123: #ifndef NO_SHOWMODE
124: char o_smd[1] = {FALSE};
125: #endif
126:
127:
128: /* The following describes the names & types of all options */
129: #define BOOL 0
130: #define NUM 1
131: #define STR 2
132: #define SET 0x01 /* this option has had its value altered */
133: #define CANSET 0x02 /* this option can be set at any time */
134: #define RCSET 0x06 /* this option can be set in a .exrc file only */
135: #define NOSAVE 0x0a /* this option should never be saved by mkexrc */
136: #define WSET 0x20 /* is this the "window" size option? */
137: #define MR 0x40 /* does this option affect the way text is displayed? */
138: struct
139: {
140: char *name; /* name of an option */
141: char *nm; /* short name of an option */
142: char type; /* type of an option */
143: char flags; /* boolean: has this option been set? */
144: char *value; /* value */
145: }
146: opts[] =
147: {
148: /* name type flags value */
149: { "autoindent", "ai", BOOL, CANSET, o_autoindent },
150: { "autoprint", "ap", BOOL, CANSET, o_autoprint },
151: { "autotab", "at", BOOL, CANSET, o_autotab },
152: { "autowrite", "aw", BOOL, CANSET, o_autowrite },
153: #ifndef CRUNCH
154: { "beautify", "bf", BOOL, CANSET, o_beautify },
155: #endif
156: #ifndef NO_ERRLIST
157: { "cc", "cc", STR, CANSET, o_cc },
158: #endif
159: #ifndef NO_CHARATTR
160: { "charattr", "ca", BOOL, CANSET|MR, o_charattr },
161: #endif
162: { "columns", "co", NUM, SET|NOSAVE|MR, o_columns },
163: #ifndef NO_DIGRAPH
164: { "digraph", "dig", BOOL, CANSET, o_digraph },
165: #endif
166: { "directory", "dir", STR, RCSET, o_directory },
167: { "edcompatible","ed", BOOL, CANSET, o_edcompatible },
168: { "equalprg", "ep", STR, CANSET, o_equalprg },
169: { "errorbells", "eb", BOOL, CANSET, o_errorbells },
170: #ifndef CRUNCH
171: { "exrc", "exrc", BOOL, CANSET, o_exrc },
172: #endif
173: { "exrefresh", "er", BOOL, CANSET, o_exrefresh },
174: { "flash", "vbell",BOOL, CANSET, o_flash },
175: #ifndef NO_DIGRAPH
176: { "flipcase", "fc", STR, CANSET, o_flipcase },
177: #endif
178: #ifndef NO_SENTENCE
179: { "hideformat", "hf", BOOL, CANSET|MR, o_hideformat },
180: #endif
181: { "ignorecase", "ic", BOOL, CANSET, o_ignorecase },
182: #ifndef NO_EXTENSIONS
183: { "inputmode", "im", BOOL, CANSET, o_inputmode },
184: #endif
185: { "keytime", "kt", NUM, CANSET, o_keytime },
186: { "keywordprg", "kp", STR, CANSET, o_keywordprg },
187: { "lines", "ls", NUM, SET|NOSAVE|MR, o_lines },
188: { "list", "li", BOOL, CANSET|MR, o_list },
189: #ifndef NO_MAGIC
190: { "magic", "ma", BOOL, CANSET, o_magic },
191: #endif
192: #ifndef NO_ERRLIST
193: { "make", "mk", STR, CANSET, o_make },
194: #endif
195: #ifndef CRUNCH
196: { "mesg", "me", BOOL, CANSET, o_mesg },
197: #endif
198: #ifndef NO_MODELINES
199: { "modelines", "ml", BOOL, CANSET, o_modelines },
200: #endif
201: #ifndef CRUNCH
202: { "more", "mo", BOOL, CANSET, o_more },
203: { "nearscroll", "ns", NUM, CANSET, o_nearscroll },
204: { "novice", "nov", BOOL, CANSET, o_novice },
205: #endif
206: { "number", "nu", BOOL, CANSET|MR, o_number },
207: #ifndef NO_SENTENCE
208: { "paragraphs", "para", STR, CANSET, o_paragraphs },
209: #endif
210: #if MSDOS
211: { "pcbios", "pc", BOOL, SET|NOSAVE, o_pcbios },
212: #endif
213: #ifndef CRUNCH
214: { "prompt", "pr", BOOL, CANSET, o_prompt },
215: #endif
216: { "readonly", "ro", BOOL, CANSET, o_readonly },
217: { "remap", "remap",BOOL, CANSET, o_remap },
218: { "report", "re", NUM, CANSET, o_report },
219: #ifndef NO_EXTENSIONS
220: { "ruler", "ru", BOOL, CANSET, o_ruler },
221: #endif
222: { "scroll", "sc", NUM, CANSET, o_scroll },
223: #ifndef NO_SENTENCE
224: { "sections", "sect", STR, CANSET, o_sections },
225: #endif
226: { "shell", "sh", STR, CANSET, o_shell },
227: #ifndef NO_SHOWMATCH
228: { "showmatch", "sm", BOOL, CANSET, o_showmatch },
229: #endif
230: #ifndef NO_SHOWMODE
231: { "showmode", "smd", BOOL, CANSET, o_smd },
232: #endif
233: { "shiftwidth", "sw", NUM, CANSET, o_shiftwidth },
234: { "sidescroll", "ss", NUM, CANSET, o_sidescroll },
235: { "sync", "sy", BOOL, CANSET, o_sync },
236: { "tabstop", "ts", NUM, CANSET|MR, o_tabstop },
237: #ifndef CRUNCH
238: { "taglength", "tl", NUM, CANSET, o_taglength },
239: #endif
240: { "term", "te", STR, SET, o_term },
241: #ifndef CRUNCH
242: { "terse", "tr", BOOL, CANSET, o_terse },
243: { "timeout", "to", BOOL, CANSET, o_keytime },
244: #endif
245: #ifndef CRUNCH
246: { "window", "wi", NUM, CANSET|MR|WSET, o_window },
247: { "wrapmargin", "wm", NUM, CANSET, o_wrapmargin },
248: #endif
249: { "wrapscan", "ws", BOOL, CANSET, o_wrapscan },
250: #ifndef CRUNCH
251: { "writeany", "wr", BOOL, CANSET, o_writeany },
252: #endif
253: { NULL, NULL, 0, CANSET, NULL }
254: };
255:
256:
257: /* This function initializes certain options from environment variables, etc. */
258: void initopts()
259: {
260: char *val;
261: int i;
262:
263: /* set some stuff from environment variables */
264: #if MSDOS
265: if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */
266: #else
267: if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
268: #endif
269: {
270: strcpy(o_shell, val);
271: }
272:
273: strcpy(o_term, termtype);
274: #if MSDOS
275: if (strcmp(termtype, "pcbios"))
276: {
277: o_pcbios[0] = FALSE;
278: }
279: else
280: {
281: o_pcbios[0] = TRUE;
282: }
283: #endif
284:
285: #if AMIGA || MSDOS || TOS
286: if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */
287: || (val = getenv("TEMP")))
288: strcpy(o_directory, val);
289: #endif
290:
291: #ifndef CRUNCH
292: if ((val = getenv("LINES")) && atoi(val) > 4) /* yes, ASSIGNMENT! */
293: {
294: LINES = atoi(val);
295: }
296: if ((val = getenv("COLUMNS")) && atoi(val) > 30) /* yes, ASSIGNMENT! */
297: {
298: COLS = atoi(val);
299: }
300: #endif
301: *o_lines = LINES;
302: *o_columns = COLS;
303: *o_scroll = LINES / 2 - 1;
304: #ifndef CRUNCH
305: if (o_window[0] == 0)
306: {
307: o_window[0] = o_window[2] = *o_lines;
308: }
309: *o_nearscroll = *o_lines;
310: #endif
311:
312: /* disable the flash option if we don't know how to do a flash */
313: if (!has_VB)
314: {
315: for (i = 0; opts[i].value != o_flash; i++)
316: {
317: }
318: opts[i].flags &= ~CANSET;
319: *o_flash = FALSE;
320: }
321:
322: #ifndef NO_DIGRAPH
323: # ifdef CS_LATIN1
324: for (i = 0, val = o_flipcase; i < 32; i++)
325: {
326: /* leave out the multiply/divide symbols */
327: if (i == 23)
328: continue;
329:
330: /* add lower/uppercase pair */
331: *val++ = i + 0xe0;
332: *val++ = i + 0xc0;
333: }
334: *val = '\0';
335: # endif /* CS_LATIN1 */
336:
337: /* initialize the ctype package */
338: _ct_init(o_flipcase);
339: #else
340: _ct_init("");
341: #endif /* not NO_DIGRAPH */
342: }
343:
344: /* This function lists the current values of all options */
345: void dumpopts(all)
346: int all; /* boolean: dump all options, or just set ones? */
347: {
348: #ifndef NO_OPTCOLS
349: int i, j, k;
350: char nbuf[4]; /* used for converting numbers to ASCII */
351: int widths[5]; /* width of each column, including gap */
352: int ncols; /* number of columns */
353: int nrows; /* number of options per column */
354: int nset; /* number of options to be output */
355: int width; /* width of a particular option */
356: int todump[60]; /* indicies of options to be dumped */
357:
358: /* step 1: count the number of set options */
359: for (nset = i = 0; opts[i].name; i++)
360: {
361: if (all || (opts[i].flags & SET))
362: {
363: todump[nset++] = i;
364: }
365: }
366:
367: /* step two: try to use as many columns as possible */
368: for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--)
369: {
370: /* how many would go in this column? */
371: nrows = (nset + ncols - 1) / ncols;
372:
373: /* figure out the width of each column */
374: for (i = 0; i < ncols; i++)
375: {
376: widths[i] = 0;
377: for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++)
378: {
379: /* figure out the width of a particular option */
380: switch (opts[todump[k]].type)
381: {
382: case BOOL:
383: if (!*opts[todump[k]].value)
384: width = 2;
385: else
386: width = 0;
387: break;
388:
389: case STR:
390: width = 3 + strlen(opts[todump[k]].value);
391: if (width > MAXWIDTH)
392: width = MAXWIDTH;
393: break;
394:
395: case NUM:
396: width = 4;
397: break;
398: }
399: width += strlen(opts[todump[k]].name);
400:
401: /* if this is the widest so far, widen col */
402: if (width > widths[i])
403: {
404: widths[i] = width;
405: }
406: }
407:
408: }
409:
410: /* if the total width is narrow enough, then use it */
411: for (width = -2, i = 0; i < ncols; i++)
412: {
413: width += widths[i] + 2;
414: }
415: if (width < COLS - 1)
416: {
417: break;
418: }
419: }
420:
421: /* step 3: output the columns */
422: nrows = (nset + ncols - 1) / ncols;
423: for (i = 0; i < nrows; i++)
424: {
425: for (j = 0; j < ncols; j++)
426: {
427: /* if we hit the end of the options, quit */
428: k = i + j * nrows;
429: if (k >= nset)
430: {
431: break;
432: }
433:
434: /* output this option's value */
435: width = 0;
436: switch (opts[todump[k]].type)
437: {
438: case BOOL:
439: if (!*opts[todump[k]].value)
440: {
441: qaddch('n');
442: qaddch('o');
443: width = 2;
444: }
445: qaddstr(opts[todump[k]].name);
446: width += strlen(opts[todump[k]].name);
447: break;
448:
449: case NUM:
450: sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value));
451: qaddstr(opts[todump[k]].name);
452: qaddch('=');
453: qaddstr(nbuf);
454: width = 4 + strlen(opts[todump[k]].name);
455: break;
456:
457: case STR:
458: qaddstr(opts[todump[k]].name);
459: qaddch('=');
460: qaddch('"');
461: strcpy(tmpblk.c, opts[todump[k]].value);
462: width = 3 + strlen(tmpblk.c);
463: if (width > MAXWIDTH)
464: {
465: width = MAXWIDTH;
466: strcpy(tmpblk.c + MAXWIDTH - 6, "...");
467: }
468: qaddstr(tmpblk.c);
469: qaddch('"');
470: width += strlen(opts[todump[k]].name);
471: break;
472: }
473:
474: /* pad the field to the correct size */
475: if (k + nrows <= nset)
476: {
477: while (width < widths[j] + 2)
478: {
479: qaddch(' ');
480: width++;
481: }
482: }
483: }
484: addch('\n');
485: exrefresh();
486: }
487: #else
488: int i;
489: int col;
490: char nbuf[4];
491:
492: for (i = col = 0; opts[i].name; i++)
493: {
494: /* if not set and not all, ignore this option */
495: if (!all && !(opts[i].flags & SET))
496: {
497: continue;
498: }
499:
500: /* align this option in one of the columns */
501: if (col > 52)
502: {
503: addch('\n');
504: col = 0;
505: }
506: else if (col > 26)
507: {
508: while (col < 52)
509: {
510: qaddch(' ');
511: col++;
512: }
513: }
514: else if (col > 0)
515: {
516: while (col < 26)
517: {
518: qaddch(' ');
519: col++;
520: }
521: }
522:
523: switch (opts[i].type)
524: {
525: case BOOL:
526: if (!*opts[i].value)
527: {
528: qaddch('n');
529: qaddch('o');
530: col += 2;
531: }
532: qaddstr(opts[i].name);
533: col += strlen(opts[i].name);
534: break;
535:
536: case NUM:
537: sprintf(nbuf, "%-3d", UCHAR(*opts[i].value));
538: qaddstr(opts[i].name);
539: qaddch('=');
540: qaddstr(nbuf);
541: col += 4 + strlen(opts[i].name);
542: break;
543:
544: case STR:
545: qaddstr(opts[i].name);
546: qaddch('=');
547: qaddch('"');
548: qaddstr(opts[i].value);
549: qaddch('"');
550: col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
551: break;
552: }
553: exrefresh();
554: }
555: if (col > 0)
556: {
557: addch('\n');
558: exrefresh();
559: }
560: #endif
561: }
562:
563: #ifndef NO_MKEXRC
564: /* This function saves the current configuration of options to a file */
565: void saveopts(fd)
566: int fd; /* file descriptor to write to */
567: {
568: int i;
569: char buf[256], *pos;
570:
571: /* write each set options */
572: for (i = 0; opts[i].name; i++)
573: {
574: /* if unset or unsettable, ignore this option */
575: if ((opts[i].flags & (SET|CANSET|NOSAVE)) != (SET|CANSET))
576: {
577: continue;
578: }
579:
580: strcpy(buf, "set ");
581: pos = &buf[4];
582: switch (opts[i].type)
583: {
584: case BOOL:
585: if (!*opts[i].value)
586: {
587: *pos++='n';
588: *pos++='o';
589: }
590: strcpy(pos, opts[i].name);
591: strcat(pos, "\n");
592: break;
593:
594: case NUM:
595: sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff);
596: break;
597:
598: case STR:
599: sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value);
600: break;
601: }
602: twrite(fd, buf, (unsigned)strlen(buf));
603: }
604: }
605: #endif
606:
607:
608: /* This function changes the values of one or more options. */
609: void setopts(assignments)
610: char *assignments; /* a string containing option assignments */
611: {
612: char *name; /* name of variable in assignments */
613: char *value; /* value of the variable */
614: char *scan; /* used for moving through strings */
615: char *build; /* used for copying chars from "scan" */
616: char *prefix; /* pointer to "neg" or "no" at front of a boolean */
617: int quote; /* boolean: inside '"' quotes? */
618: int i, j;
619:
620: #ifndef CRUNCH
621: /* reset the upper limit of "window" option to lines-1 */
622: *o_window = *o_lines - 1;
623: #endif
624:
625: /* for each assignment... */
626: for (name = assignments; *name; )
627: {
628: /* skip whitespace */
629: if (*name == ' ' || *name == '\t')
630: {
631: name++;
632: continue;
633: }
634:
635: /* after the name, find the value (if any) */
636: for (scan = name; isalnum(*scan); scan++)
637: {
638: }
639: if (*scan == '=')
640: {
641: *scan++ = '\0';
642: value = build = scan;
643: for (quote = FALSE; *scan && (quote || !isspace(*scan)); scan++)
644: {
645: if (*scan == '"')
646: {
647: quote = !quote;
648: }
649: else if (*scan == '\\' && scan[1])
650: {
651: *build++ = *++scan;
652: }
653: else
654: {
655: *build++ = *scan;
656: }
657: }
658: if (*scan)
659: scan++;
660: *build = '\0';
661: }
662: else /* no "=" so it is probably boolean... */
663: {
664: if (*scan)
665: {
666: *scan++ = '\0';
667: }
668: value = NULL;
669: prefix = name;
670: #ifndef CRUNCH
671: if (!strcmp(name, "novice"))
672: /* don't check for a "no" prefix */;
673: else
674: #endif
675: if (prefix[0] == 'n' && prefix[1] == 'o')
676: name += 2;
677: else if (prefix[0] == 'n' && prefix[1] == 'e' && prefix[2] == 'g')
678: name += 3;
679: }
680:
681: /* find the variable */
682: for (i = 0;
683: opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
684: i++)
685: {
686: }
687:
688: /* change the variable */
689: if (!opts[i].name)
690: {
691: msg("invalid option name \"%s\"", name);
692: }
693: else if ((opts[i].flags & CANSET) != CANSET)
694: {
695: msg("option \"%s\" can't be altered", name);
696: }
697: else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L)
698: {
699: msg("option \"%s\" can only be set in a %s file", name, EXRC);
700: }
701: else if (value)
702: {
703: switch (opts[i].type)
704: {
705: case BOOL:
706: msg("option \"[no]%s\" is boolean", name);
707: break;
708:
709: case NUM:
710: j = atoi(value);
711: if (j == 0 && *value != '0')
712: {
713: msg("option \"%s\" must have a numeric value", name);
714: }
715: else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
716: {
717: msg("option \"%s\" must have a value between %d and %d",
718: name, opts[i].value[1], opts[i].value[2] & 0xff);
719: }
720: else
721: {
722: *opts[i].value = atoi(value);
723: opts[i].flags |= SET;
724: }
725: break;
726:
727: case STR:
728: strcpy(opts[i].value, value);
729: opts[i].flags |= SET;
730: break;
731: }
732: if (opts[i].flags & MR)
733: {
734: redraw(MARK_UNSET, FALSE);
735: }
736: #ifndef CRUNCH
737: if (opts[i].flags & WSET)
738: {
739: wset = TRUE;
740: }
741: #endif
742: }
743: else /* valid option, no value */
744: {
745: if (opts[i].type == BOOL)
746: {
747: if (prefix == name)
748: *opts[i].value = TRUE;
749: else if (prefix[1] == 'o')
750: *opts[i].value = FALSE;
751: else
752: *opts[i].value = !*opts[i].value;
753:
754: opts[i].flags |= SET;
755: if (opts[i].flags & MR)
756: {
757: redraw(MARK_UNSET, FALSE);
758: }
759: }
760: else
761: {
762: msg("option \"%s\" must be given a value", name);
763: }
764: }
765:
766: /* move on to the next option */
767: name = scan;
768: }
769:
770: /* special processing ... */
771:
772: #ifndef CRUNCH
773: /* if "novice" is set, then ":set report=1 showmode nomagic" */
774: if (*o_novice)
775: {
776: *o_report = 1;
777: # ifndef NO_SHOWMODE
778: *o_smd = TRUE;
779: # endif
780: # ifndef NO_MAGIC
781: *o_magic = FALSE;
782: # endif
783: }
784: #endif
785:
786: /* if "readonly" then set the READONLY flag for this file */
787: if (*o_readonly)
788: {
789: setflag(file, READONLY);
790: }
791:
792: #ifndef NO_DIGRAPH
793: /* re-initialize the ctype package */
794: _ct_init(o_flipcase);
795: #endif /* not NO_DIGRAPH */
796:
797: /* copy o_lines and o_columns into LINES and COLS */
798: LINES = (*o_lines & 255);
799: COLS = (*o_columns & 255);
800: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.