spl->critical section conversion.
[dragonfly.git] / contrib / less-381 / optfunc.c
1 /*
2  * Copyright (C) 1984-2002  Mark Nudelman
3  *
4  * You may distribute under the terms of either the GNU General Public
5  * License or the Less License, as specified in the README file.
6  *
7  * For more information about less, or for information on how to 
8  * contact the author, see the README file.
9  */
10
11
12 /*
13  * Handling functions for command line options.
14  *
15  * Most options are handled by the generic code in option.c.
16  * But all string options, and a few non-string options, require
17  * special handling specific to the particular option.
18  * This special processing is done by the "handling functions" in this file.
19  *
20  * Each handling function is passed a "type" and, if it is a string
21  * option, the string which should be "assigned" to the option.
22  * The type may be one of:
23  *      INIT    The option is being initialized from the command line.
24  *      TOGGLE  The option is being changed from within the program.
25  *      QUERY   The setting of the option is merely being queried.
26  */
27
28 #include "less.h"
29 #include "option.h"
30
31 extern int nbufs;
32 extern int bufspace;
33 extern int pr_type;
34 extern int plusoption;
35 extern int swindow;
36 extern int sc_height;
37 extern int secure;
38 extern int dohelp;
39 extern int any_display;
40 extern char openquote;
41 extern char closequote;
42 extern char *prproto[];
43 extern char *eqproto;
44 extern char *hproto;
45 extern char *wproto;
46 extern IFILE curr_ifile;
47 extern char version[];
48 #if LOGFILE
49 extern char *namelogfile;
50 extern int force_logfile;
51 extern int logfile;
52 #endif
53 #if TAGS
54 public char *tagoption = NULL;
55 extern char *tags;
56 extern int jump_sline;
57 #endif
58 #if MSDOS_COMPILER
59 extern int nm_fg_color, nm_bg_color;
60 extern int bo_fg_color, bo_bg_color;
61 extern int ul_fg_color, ul_bg_color;
62 extern int so_fg_color, so_bg_color;
63 extern int bl_fg_color, bl_bg_color;
64 #endif
65
66
67 #if LOGFILE
68 /*
69  * Handler for -o option.
70  */
71         public void
72 opt_o(type, s)
73         int type;
74         char *s;
75 {
76         PARG parg;
77
78         if (secure)
79         {
80                 error("log file support is not available", NULL_PARG);
81                 return;
82         }
83         switch (type)
84         {
85         case INIT:
86                 namelogfile = s;
87                 break;
88         case TOGGLE:
89                 if (ch_getflags() & CH_CANSEEK)
90                 {
91                         error("Input is not a pipe", NULL_PARG);
92                         return;
93                 }
94                 if (logfile >= 0)
95                 {
96                         error("Log file is already in use", NULL_PARG);
97                         return;
98                 }
99                 s = skipsp(s);
100                 namelogfile = lglob(s);
101                 use_logfile(namelogfile);
102                 sync_logfile();
103                 break;
104         case QUERY:
105                 if (logfile < 0)
106                         error("No log file", NULL_PARG);
107                 else
108                 {
109                         parg.p_string = namelogfile;
110                         error("Log file \"%s\"", &parg);
111                 }
112                 break;
113         }
114 }
115
116 /*
117  * Handler for -O option.
118  */
119         public void
120 opt__O(type, s)
121         int type;
122         char *s;
123 {
124         force_logfile = TRUE;
125         opt_o(type, s);
126 }
127 #endif
128
129 /*
130  * Handlers for -l option.
131  */
132         public void
133 opt_l(type, s)
134         int type;
135         char *s;
136 {
137         int err;
138         int n;
139         char *t;
140         
141         switch (type)
142         {
143         case INIT:
144                 t = s;
145                 n = getnum(&t, "l", &err);
146                 if (err || n <= 0)
147                 {
148                         error("Line number is required after -l", NULL_PARG);
149                         return;
150                 }
151                 plusoption = TRUE;
152                 ungetsc(s);
153                 break;
154         }
155 }
156
157 #if USERFILE
158         public void
159 opt_k(type, s)
160         int type;
161         char *s;
162 {
163         PARG parg;
164
165         switch (type)
166         {
167         case INIT:
168                 if (lesskey(s, 0))
169                 {
170                         parg.p_string = s;
171                         error("Cannot use lesskey file \"%s\"", &parg);
172                 }
173                 break;
174         }
175 }
176 #endif
177
178 #if TAGS
179 /*
180  * Handler for -t option.
181  */
182         public void
183 opt_t(type, s)
184         int type;
185         char *s;
186 {
187         IFILE save_ifile;
188         POSITION pos;
189
190         switch (type)
191         {
192         case INIT:
193                 tagoption = s;
194                 /* Do the rest in main() */
195                 break;
196         case TOGGLE:
197                 if (secure)
198                 {
199                         error("tags support is not available", NULL_PARG);
200                         break;
201                 }
202                 findtag(skipsp(s));
203                 save_ifile = save_curr_ifile();
204                 if (edit_tagfile())
205                         break;
206                 if ((pos = tagsearch()) == NULL_POSITION)
207                 {
208                         reedit_ifile(save_ifile);
209                         break;
210                 }
211                 unsave_ifile(save_ifile);
212                 jump_loc(pos, jump_sline);
213                 break;
214         }
215 }
216
217 /*
218  * Handler for -T option.
219  */
220         public void
221 opt__T(type, s)
222         int type;
223         char *s;
224 {
225         PARG parg;
226
227         switch (type)
228         {
229         case INIT:
230                 tags = s;
231                 break;
232         case TOGGLE:
233                 s = skipsp(s);
234                 tags = lglob(s);
235                 break;
236         case QUERY:
237                 parg.p_string = tags;
238                 error("Tags file \"%s\"", &parg);
239                 break;
240         }
241 }
242 #endif
243
244 /*
245  * Handler for -p option.
246  */
247         public void
248 opt_p(type, s)
249         int type;
250         register char *s;
251 {
252         switch (type)
253         {
254         case INIT:
255                 /*
256                  * Unget a search command for the specified string.
257                  * {{ This won't work if the "/" command is
258                  *    changed or invalidated by a .lesskey file. }}
259                  */
260                 plusoption = TRUE;
261                 ungetsc(s);
262                 ungetsc("/");
263                 break;
264         }
265 }
266
267 /*
268  * Handler for -P option.
269  */
270         public void
271 opt__P(type, s)
272         int type;
273         register char *s;
274 {
275         register char **proto;
276         PARG parg;
277
278         switch (type)
279         {
280         case INIT:
281         case TOGGLE:
282                 /*
283                  * Figure out which prototype string should be changed.
284                  */
285                 switch (*s)
286                 {
287                 case 's':  proto = &prproto[PR_SHORT];  s++;    break;
288                 case 'm':  proto = &prproto[PR_MEDIUM]; s++;    break;
289                 case 'M':  proto = &prproto[PR_LONG];   s++;    break;
290                 case '=':  proto = &eqproto;            s++;    break;
291                 case 'h':  proto = &hproto;             s++;    break;
292                 case 'w':  proto = &wproto;             s++;    break;
293                 default:   proto = &prproto[PR_SHORT];          break;
294                 }
295                 free(*proto);
296                 *proto = save(s);
297                 break;
298         case QUERY:
299                 parg.p_string = prproto[pr_type];
300                 error("%s", &parg);
301                 break;
302         }
303 }
304
305 /*
306  * Handler for the -b option.
307  */
308         /*ARGSUSED*/
309         public void
310 opt_b(type, s)
311         int type;
312         char *s;
313 {
314         switch (type)
315         {
316         case INIT:
317         case TOGGLE:
318                 /*
319                  * Set the new number of buffers.
320                  */
321                 ch_setbufspace(bufspace);
322                 break;
323         case QUERY:
324                 break;
325         }
326 }
327
328 /*
329  * Handler for the -i option.
330  */
331         /*ARGSUSED*/
332         public void
333 opt_i(type, s)
334         int type;
335         char *s;
336 {
337         switch (type)
338         {
339         case TOGGLE:
340                 chg_caseless();
341                 break;
342         case QUERY:
343         case INIT:
344                 break;
345         }
346 }
347
348 /*
349  * Handler for the -V option.
350  */
351         /*ARGSUSED*/
352         public void
353 opt__V(type, s)
354         int type;
355         char *s;
356 {
357         switch (type)
358         {
359         case TOGGLE:
360         case QUERY:
361                 dispversion();
362                 break;
363         case INIT:
364                 /*
365                  * Force output to stdout per GNU standard for --version output.
366                  */
367                 any_display = 1;
368                 putstr("less ");
369                 putstr(version);
370                 putstr("\nCopyright (C) 2002 Mark Nudelman\n\n");
371                 putstr("less comes with NO WARRANTY, to the extent permitted by law.\n");
372                 putstr("For information about the terms of redistribution,\n");
373                 putstr("see the file named README in the less distribution.\n");
374                 putstr("Homepage: http://www.greenwoodsoftware.com/less\n");
375                 quit(QUIT_OK);
376                 break;
377         }
378 }
379
380 #if MSDOS_COMPILER
381 /*
382  * Parse an MSDOS color descriptor.
383  */
384         static void
385 colordesc(s, fg_color, bg_color)
386         char *s;
387         int *fg_color;
388         int *bg_color;
389 {
390         int fg, bg;
391         int err;
392         
393         fg = getnum(&s, "D", &err);
394         if (err)
395         {
396                 error("Missing fg color in -D", NULL_PARG);
397                 return;
398         }
399         if (*s != '.')
400                 bg = 0;
401         else
402         {
403                 s++;
404                 bg = getnum(&s, "D", &err);
405                 if (err)
406                 {
407                         error("Missing fg color in -D", NULL_PARG);
408                         return;
409                 }
410         }
411         if (*s != '\0')
412                 error("Extra characters at end of -D option", NULL_PARG);
413         *fg_color = fg;
414         *bg_color = bg;
415 }
416
417 /*
418  * Handler for the -D option.
419  */
420         /*ARGSUSED*/
421         public void
422 opt_D(type, s)
423         int type;
424         char *s;
425 {
426         switch (type)
427         {
428         case INIT:
429         case TOGGLE:
430                 switch (*s++)
431                 {
432                 case 'n':
433                         colordesc(s, &nm_fg_color, &nm_bg_color);
434                         break;
435                 case 'd':
436                         colordesc(s, &bo_fg_color, &bo_bg_color);
437                         break;
438                 case 'u':
439                         colordesc(s, &ul_fg_color, &ul_bg_color);
440                         break;
441                 case 'k':
442                         colordesc(s, &bl_fg_color, &bl_bg_color);
443                         break;
444                 case 's':
445                         colordesc(s, &so_fg_color, &so_bg_color);
446                         break;
447                 default:
448                         error("-D must be followed by n, d, u, k or s", NULL_PARG);
449                         break;
450                 }
451                 if (type == TOGGLE)
452                 {
453                         so_enter();
454                         so_exit();
455                 }
456                 break;
457         case QUERY:
458                 break;
459         }
460 }
461 #endif
462
463 /*
464  * Handler for the -x option.
465  */
466         public void
467 opt_x(type, s)
468         int type;
469         register char *s;
470 {
471         extern int tabstops[];
472         extern int ntabstops;
473         extern int tabdefault;
474         char msg[60+(4*TABSTOP_MAX)];
475         int i;
476         PARG p;
477
478         switch (type)
479         {
480         case INIT:
481         case TOGGLE:
482                 /* Start at 1 because tabstops[0] is always zero. */
483                 for (i = 1;  i < TABSTOP_MAX;  )
484                 {
485                         int n = 0;
486                         s = skipsp(s);
487                         while (*s >= '0' && *s <= '9')
488                                 n = (10 * n) + (*s++ - '0');
489                         if (n > tabstops[i-1])
490                                 tabstops[i++] = n;
491                         s = skipsp(s);
492                         if (*s++ != ',')
493                                 break;
494                 }
495                 if (i < 2)
496                         return;
497                 ntabstops = i;
498                 tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2];
499                 break;
500         case QUERY:
501                 strcpy(msg, "Tab stops ");
502                 if (ntabstops > 2)
503                 {
504                         for (i = 1;  i < ntabstops;  i++)
505                         {
506                                 if (i > 1)
507                                         strcat(msg, ",");
508                                 sprintf(msg+strlen(msg), "%d", tabstops[i]);
509                         }
510                         sprintf(msg+strlen(msg), " and then ");
511                 }
512                 sprintf(msg+strlen(msg), "every %d spaces",
513                         tabdefault);
514                 p.p_string = msg;
515                 error("%s", &p);
516                 break;
517         }
518 }
519
520
521 /*
522  * Handler for the -" option.
523  */
524         public void
525 opt_quote(type, s)
526         int type;
527         register char *s;
528 {
529         char buf[3];
530         PARG parg;
531
532         switch (type)
533         {
534         case INIT:
535         case TOGGLE:
536                 if (s[0] == '\0')
537                 {
538                         openquote = closequote = '\0';
539                         break;
540                 }
541                 if (s[1] != '\0' && s[2] != '\0')
542                 {
543                         error("-\" must be followed by 1 or 2 chars", NULL_PARG);
544                         return;
545                 }
546                 openquote = s[0];
547                 if (s[1] == '\0')
548                         closequote = openquote;
549                 else
550                         closequote = s[1];
551                 break;
552         case QUERY:
553                 buf[0] = openquote;
554                 buf[1] = closequote;
555                 buf[2] = '\0';
556                 parg.p_string = buf;
557                 error("quotes %s", &parg);
558                 break;
559         }
560 }
561
562 /*
563  * "-?" means display a help message.
564  * If from the command line, exit immediately.
565  */
566         /*ARGSUSED*/
567         public void
568 opt_query(type, s)
569         int type;
570         char *s;
571 {
572         switch (type)
573         {
574         case QUERY:
575         case TOGGLE:
576                 error("Use \"h\" for help", NULL_PARG);
577                 break;
578         case INIT:
579                 dohelp = 1;
580         }
581 }
582
583 /*
584  * Get the "screen window" size.
585  */
586         public int
587 get_swindow()
588 {
589         if (swindow > 0)
590                 return (swindow);
591         return (sc_height + swindow);
592 }
593