]> www.wagner.pp.ru Git - oss/less.git/blob - optfunc.c
Removed code page operation. Fix GLOB macros for 64-bit win32. Fixed debug flags...
[oss/less.git] / optfunc.c
1 /*
2  * Copyright (C) 1984-2015  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, see the README file.
8  */
9
10
11 /*
12  * Handling functions for command line options.
13  *
14  * Most options are handled by the generic code in option.c.
15  * But all string options, and a few non-string options, require
16  * special handling specific to the particular option.
17  * This special processing is done by the "handling functions" in this file.
18  *
19  * Each handling function is passed a "type" and, if it is a string
20  * option, the string which should be "assigned" to the option.
21  * The type may be one of:
22  *      INIT    The option is being initialized from the command line.
23  *      TOGGLE  The option is being changed from within the program.
24  *      QUERY   The setting of the option is merely being queried.
25  */
26
27 #include "less.h"
28 #include "option.h"
29
30 extern int nbufs;
31 extern int bufspace;
32 extern int pr_type;
33 extern int plusoption;
34 extern int swindow;
35 extern int sc_width;
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 char *every_first_cmd;
47 extern IFILE curr_ifile;
48 extern char version[];
49 extern int jump_sline;
50 extern int jump_sline_fraction;
51 extern int shift_count;
52 extern int shift_count_fraction;
53 extern int less_is_more;
54 #if LOGFILE
55 extern char *namelogfile;
56 extern int force_logfile;
57 extern int logfile;
58 #endif
59 #if TAGS
60 public char *tagoption = NULL;
61 extern char *tags;
62 extern char ztags[];
63 #endif
64 #if MSDOS_COMPILER
65 extern int nm_fg_color, nm_bg_color;
66 extern int bo_fg_color, bo_bg_color;
67 extern int ul_fg_color, ul_bg_color;
68 extern int so_fg_color, so_bg_color;
69 extern int bl_fg_color, bl_bg_color;
70 #endif
71
72
73 #if LOGFILE
74 /*
75  * Handler for -o option.
76  */
77         public void
78 opt_o(type, s)
79         int type;
80         char *s;
81 {
82         PARG parg;
83
84         if (secure)
85         {
86                 error("log file support is not available", NULL_PARG);
87                 return;
88         }
89         switch (type)
90         {
91         case INIT:
92                 namelogfile = save(s);
93                 break;
94         case TOGGLE:
95                 if (ch_getflags() & CH_CANSEEK)
96                 {
97                         error("Input is not a pipe", NULL_PARG);
98                         return;
99                 }
100                 if (logfile >= 0)
101                 {
102                         error("Log file is already in use", NULL_PARG);
103                         return;
104                 }
105                 s = skipsp(s);
106                 if (namelogfile != NULL)
107                         free(namelogfile);
108                 namelogfile = lglob(s);
109                 use_logfile(namelogfile);
110                 sync_logfile();
111                 break;
112         case QUERY:
113                 if (logfile < 0)
114                         error("No log file", NULL_PARG);
115                 else
116                 {
117                         parg.p_string = namelogfile;
118                         error("Log file \"%s\"", &parg);
119                 }
120                 break;
121         }
122 }
123
124 /*
125  * Handler for -O option.
126  */
127         public void
128 opt__O(type, s)
129         int type;
130         char *s;
131 {
132         force_logfile = TRUE;
133         opt_o(type, s);
134 }
135 #endif
136
137 /*
138  * Handlers for -j option.
139  */
140         public void
141 opt_j(type, s)
142         int type;
143         char *s;
144 {
145         PARG parg;
146         char buf[16];
147         int len;
148         int err;
149
150         switch (type)
151         {
152         case INIT:
153         case TOGGLE:
154                 if (*s == '.')
155                 {
156                         s++;
157                         jump_sline_fraction = getfraction(&s, "j", &err);
158                         if (err)
159                                 error("Invalid line fraction", NULL_PARG);
160                         else
161                                 calc_jump_sline();
162                 } else
163                 {
164                         int sline = getnum(&s, "j", &err);
165                         if (err)
166                                 error("Invalid line number", NULL_PARG);
167                         else
168                         {
169                                 jump_sline = sline;
170                                 jump_sline_fraction = -1;
171                         }
172                 }
173                 break;
174         case QUERY:
175                 if (jump_sline_fraction < 0)
176                 {
177                         parg.p_int =  jump_sline;
178                         error("Position target at screen line %d", &parg);
179                 } else
180                 {
181
182                         sprintf(buf, ".%06d", jump_sline_fraction);
183                         len = (int) strlen(buf);
184                         while (len > 2 && buf[len-1] == '0')
185                                 len--;
186                         buf[len] = '\0';
187                         parg.p_string = buf;
188                         error("Position target at screen position %s", &parg);
189                 }
190                 break;
191         }
192 }
193
194         public void
195 calc_jump_sline()
196 {
197         if (jump_sline_fraction < 0)
198                 return;
199         jump_sline = sc_height * jump_sline_fraction / NUM_FRAC_DENOM;
200 }
201
202 /*
203  * Handlers for -# option.
204  */
205         public void
206 opt_shift(type, s)
207         int type;
208         char *s;
209 {
210         PARG parg;
211         char buf[16];
212         int len;
213         int err;
214
215         switch (type)
216         {
217         case INIT:
218         case TOGGLE:
219                 if (*s == '.')
220                 {
221                         s++;
222                         shift_count_fraction = getfraction(&s, "#", &err);
223                         if (err)
224                                 error("Invalid column fraction", NULL_PARG);
225                         else
226                                 calc_shift_count();
227                 } else
228                 {
229                         int hs = getnum(&s, "#", &err);
230                         if (err)
231                                 error("Invalid column number", NULL_PARG);
232                         else
233                         {
234                                 shift_count = hs;
235                                 shift_count_fraction = -1;
236                         }
237                 }
238                 break;
239         case QUERY:
240                 if (shift_count_fraction < 0)
241                 {
242                         parg.p_int = shift_count;
243                         error("Horizontal shift %d columns", &parg);
244                 } else
245                 {
246
247                         sprintf(buf, ".%06d", shift_count_fraction);
248                         len = (int) strlen(buf);
249                         while (len > 2 && buf[len-1] == '0')
250                                 len--;
251                         buf[len] = '\0';
252                         parg.p_string = buf;
253                         error("Horizontal shift %s of screen width", &parg);
254                 }
255                 break;
256         }
257 }
258         public void
259 calc_shift_count()
260 {
261         if (shift_count_fraction < 0)
262                 return;
263         shift_count = sc_width * shift_count_fraction / NUM_FRAC_DENOM;
264 }
265
266 #if USERFILE
267         public void
268 opt_k(type, s)
269         int type;
270         char *s;
271 {
272         PARG parg;
273
274         switch (type)
275         {
276         case INIT:
277                 if (lesskey(s, 0))
278                 {
279                         parg.p_string = s;
280                         error("Cannot use lesskey file \"%s\"", &parg);
281                 }
282                 break;
283         }
284 }
285 #endif
286
287 #if TAGS
288 /*
289  * Handler for -t option.
290  */
291         public void
292 opt_t(type, s)
293         int type;
294         char *s;
295 {
296         IFILE save_ifile;
297         POSITION pos;
298
299         switch (type)
300         {
301         case INIT:
302                 tagoption = save(s);
303                 /* Do the rest in main() */
304                 break;
305         case TOGGLE:
306                 if (secure)
307                 {
308                         error("tags support is not available", NULL_PARG);
309                         break;
310                 }
311                 findtag(skipsp(s));
312                 save_ifile = save_curr_ifile();
313                 /*
314                  * Try to open the file containing the tag
315                  * and search for the tag in that file.
316                  */
317                 if (edit_tagfile() || (pos = tagsearch()) == NULL_POSITION)
318                 {
319                         /* Failed: reopen the old file. */
320                         reedit_ifile(save_ifile);
321                         break;
322                 }
323                 unsave_ifile(save_ifile);
324                 jump_loc(pos, jump_sline);
325                 break;
326         }
327 }
328
329 /*
330  * Handler for -T option.
331  */
332         public void
333 opt__T(type, s)
334         int type;
335         char *s;
336 {
337         PARG parg;
338
339         switch (type)
340         {
341         case INIT:
342                 tags = save(s);
343                 break;
344         case TOGGLE:
345                 s = skipsp(s);
346                 if (tags != NULL && tags != ztags)
347                         free(tags);
348                 tags = lglob(s);
349                 break;
350         case QUERY:
351                 parg.p_string = tags;
352                 error("Tags file \"%s\"", &parg);
353                 break;
354         }
355 }
356 #endif
357
358 /*
359  * Handler for -p option.
360  */
361         public void
362 opt_p(type, s)
363         int type;
364         register char *s;
365 {
366         switch (type)
367         {
368         case INIT:
369                 /*
370                  * Unget a command for the specified string.
371                  */
372                 if (less_is_more)
373                 {
374                         /*
375                          * In "more" mode, the -p argument is a command,
376                          * not a search string, so we don't need a slash.
377                          */
378                         every_first_cmd = save(s);
379                 } else
380                 {
381                         plusoption = TRUE;
382                         ungetcc(CHAR_END_COMMAND);
383                         ungetsc(s);
384                          /*
385                           * {{ This won't work if the "/" command is
386                           *    changed or invalidated by a .lesskey file. }}
387                           */
388                         ungetsc("/");
389                 }
390                 break;
391         }
392 }
393
394 /*
395  * Handler for -P option.
396  */
397         public void
398 opt__P(type, s)
399         int type;
400         register char *s;
401 {
402         register char **proto;
403         PARG parg;
404
405         switch (type)
406         {
407         case INIT:
408         case TOGGLE:
409                 /*
410                  * Figure out which prototype string should be changed.
411                  */
412                 switch (*s)
413                 {
414                 case 's':  proto = &prproto[PR_SHORT];  s++;    break;
415                 case 'm':  proto = &prproto[PR_MEDIUM]; s++;    break;
416                 case 'M':  proto = &prproto[PR_LONG];   s++;    break;
417                 case '=':  proto = &eqproto;            s++;    break;
418                 case 'h':  proto = &hproto;             s++;    break;
419                 case 'w':  proto = &wproto;             s++;    break;
420                 default:   proto = &prproto[PR_SHORT];          break;
421                 }
422                 free(*proto);
423                 *proto = save(s);
424                 break;
425         case QUERY:
426                 parg.p_string = prproto[pr_type];
427                 error("%s", &parg);
428                 break;
429         }
430 }
431
432 /*
433  * Handler for the -b option.
434  */
435         /*ARGSUSED*/
436         public void
437 opt_b(type, s)
438         int type;
439         char *s;
440 {
441         switch (type)
442         {
443         case INIT:
444         case TOGGLE:
445                 /*
446                  * Set the new number of buffers.
447                  */
448                 ch_setbufspace(bufspace);
449                 break;
450         case QUERY:
451                 break;
452         }
453 }
454
455 /*
456  * Handler for the -i option.
457  */
458         /*ARGSUSED*/
459         public void
460 opt_i(type, s)
461         int type;
462         char *s;
463 {
464         switch (type)
465         {
466         case TOGGLE:
467                 chg_caseless();
468                 break;
469         case QUERY:
470         case INIT:
471                 break;
472         }
473 }
474
475 /*
476  * Handler for the -V option.
477  */
478         /*ARGSUSED*/
479         public void
480 opt__V(type, s)
481         int type;
482         char *s;
483 {
484         switch (type)
485         {
486         case TOGGLE:
487         case QUERY:
488                 dispversion();
489                 break;
490         case INIT:
491                 /*
492                  * Force output to stdout per GNU standard for --version output.
493                  */
494                 any_display = 1;
495                 putstr("less ");
496                 putstr(version);
497                 putstr(" (");
498 #if HAVE_GNU_REGEX
499                 putstr("GNU ");
500 #endif
501 #if HAVE_POSIX_REGCOMP
502                 putstr("POSIX ");
503 #endif
504 #if HAVE_PCRE
505                 putstr("PCRE ");
506 #endif
507 #if HAVE_RE_COMP
508                 putstr("BSD ");
509 #endif
510 #if HAVE_REGCMP
511                 putstr("V8 ");
512 #endif
513 #if HAVE_V8_REGCOMP
514                 putstr("Spencer V8 ");
515 #endif
516 #if !HAVE_GNU_REGEX && !HAVE_POSIX_REGCOMP && !HAVE_PCRE && !HAVE_RE_COMP && !HAVE_REGCMP && !HAVE_V8_REGCOMP
517                 putstr("no ");
518 #endif
519                 putstr("regular expressions)\n");
520                 putstr("Copyright (C) 1984-2015  Mark Nudelman\n\n");
521                 putstr("less comes with NO WARRANTY, to the extent permitted by law.\n");
522                 putstr("For information about the terms of redistribution,\n");
523                 putstr("see the file named README in the less distribution.\n");
524                 putstr("Homepage: http://www.greenwoodsoftware.com/less\n");
525                 quit(QUIT_OK);
526                 break;
527         }
528 }
529
530 #if MSDOS_COMPILER
531 /*
532  * Parse an MSDOS color descriptor.
533  */
534         static void
535 colordesc(s, fg_color, bg_color)
536         char *s;
537         int *fg_color;
538         int *bg_color;
539 {
540         int fg, bg;
541         int err;
542         
543         fg = getnum(&s, "D", &err);
544         if (err)
545         {
546                 error("Missing fg color in -D", NULL_PARG);
547                 return;
548         }
549         if (*s != '.')
550                 bg = nm_bg_color;
551         else
552         {
553                 s++;
554                 bg = getnum(&s, "D", &err);
555                 if (err)
556                 {
557                         error("Missing bg color in -D", NULL_PARG);
558                         return;
559                 }
560         }
561         if (*s != '\0')
562                 error("Extra characters at end of -D option", NULL_PARG);
563         *fg_color = fg;
564         *bg_color = bg;
565 }
566
567 /*
568  * Handler for the -D option.
569  */
570         /*ARGSUSED*/
571         public void
572 opt_D(type, s)
573         int type;
574         char *s;
575 {
576         switch (type)
577         {
578         case INIT:
579         case TOGGLE:
580                 switch (*s++)
581                 {
582                 case 'n':
583                         colordesc(s, &nm_fg_color, &nm_bg_color);
584                         break;
585                 case 'd':
586                         colordesc(s, &bo_fg_color, &bo_bg_color);
587                         break;
588                 case 'u':
589                         colordesc(s, &ul_fg_color, &ul_bg_color);
590                         break;
591                 case 'k':
592                         colordesc(s, &bl_fg_color, &bl_bg_color);
593                         break;
594                 case 's':
595                         colordesc(s, &so_fg_color, &so_bg_color);
596                         break;
597                 default:
598                         error("-D must be followed by n, d, u, k or s", NULL_PARG);
599                         break;
600                 }
601                 if (type == TOGGLE)
602                 {
603                         at_enter(AT_STANDOUT);
604                         at_exit();
605                 }
606                 break;
607         case QUERY:
608                 break;
609         }
610 }
611 #endif
612
613 /*
614  * Handler for the -x option.
615  */
616         public void
617 opt_x(type, s)
618         int type;
619         register char *s;
620 {
621         extern int tabstops[];
622         extern int ntabstops;
623         extern int tabdefault;
624         char msg[60+(4*TABSTOP_MAX)];
625         int i;
626         PARG p;
627
628         switch (type)
629         {
630         case INIT:
631         case TOGGLE:
632                 /* Start at 1 because tabstops[0] is always zero. */
633                 for (i = 1;  i < TABSTOP_MAX;  )
634                 {
635                         int n = 0;
636                         s = skipsp(s);
637                         while (*s >= '0' && *s <= '9')
638                                 n = (10 * n) + (*s++ - '0');
639                         if (n > tabstops[i-1])
640                                 tabstops[i++] = n;
641                         s = skipsp(s);
642                         if (*s++ != ',')
643                                 break;
644                 }
645                 if (i < 2)
646                         return;
647                 ntabstops = i;
648                 tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2];
649                 break;
650         case QUERY:
651                 strcpy(msg, "Tab stops ");
652                 if (ntabstops > 2)
653                 {
654                         for (i = 1;  i < ntabstops;  i++)
655                         {
656                                 if (i > 1)
657                                         strcat(msg, ",");
658                                 sprintf(msg+strlen(msg), "%d", tabstops[i]);
659                         }
660                         sprintf(msg+strlen(msg), " and then ");
661                 }
662                 sprintf(msg+strlen(msg), "every %d spaces",
663                         tabdefault);
664                 p.p_string = msg;
665                 error("%s", &p);
666                 break;
667         }
668 }
669
670
671 /*
672  * Handler for the -" option.
673  */
674         public void
675 opt_quote(type, s)
676         int type;
677         register char *s;
678 {
679         char buf[3];
680         PARG parg;
681
682         switch (type)
683         {
684         case INIT:
685         case TOGGLE:
686                 if (s[0] == '\0')
687                 {
688                         openquote = closequote = '\0';
689                         break;
690                 }
691                 if (s[1] != '\0' && s[2] != '\0')
692                 {
693                         error("-\" must be followed by 1 or 2 chars", NULL_PARG);
694                         return;
695                 }
696                 openquote = s[0];
697                 if (s[1] == '\0')
698                         closequote = openquote;
699                 else
700                         closequote = s[1];
701                 break;
702         case QUERY:
703                 buf[0] = openquote;
704                 buf[1] = closequote;
705                 buf[2] = '\0';
706                 parg.p_string = buf;
707                 error("quotes %s", &parg);
708                 break;
709         }
710 }
711
712 /*
713  * "-?" means display a help message.
714  * If from the command line, exit immediately.
715  */
716         /*ARGSUSED*/
717         public void
718 opt_query(type, s)
719         int type;
720         char *s;
721 {
722         switch (type)
723         {
724         case QUERY:
725         case TOGGLE:
726                 error("Use \"h\" for help", NULL_PARG);
727                 break;
728         case INIT:
729                 dohelp = 1;
730         }
731 }
732
733 /*
734  * Get the "screen window" size.
735  */
736         public int
737 get_swindow()
738 {
739         if (swindow > 0)
740                 return (swindow);
741         return (sc_height + swindow);
742 }
743