1/*
2 * Copyright (C) 1984-2021  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#define NEWBOT 1
11
12/*
13 * Standard include file for "less".
14 */
15
16/*
17 * Defines for MSDOS_COMPILER.
18 */
19#define MSOFTC          1   /* Microsoft C */
20#define BORLANDC        2   /* Borland C */
21#define WIN32C          3   /* Windows (Borland C or Microsoft C) */
22#define DJGPPC          4   /* DJGPP C */
23
24/*
25 * Include the file of compile-time options.
26 * The <> make cc search for it in -I., not srcdir.
27 */
28#include <defines.h>
29
30#ifdef _SEQUENT_
31/*
32 * Kludge for Sequent Dynix systems that have sigsetmask, but
33 * it's not compatible with the way less calls it.
34 * {{ Do other systems need this? }}
35 */
36#undef HAVE_SIGSETMASK
37#endif
38
39/*
40 * Language details.
41 */
42#if HAVE_ANSI_PROTOS
43#define LESSPARAMS(a) a
44#else
45#define LESSPARAMS(a) ()
46#endif
47#if HAVE_VOID
48#define VOID_POINTER    void *
49#define VOID_PARAM      void
50#else
51#define VOID_POINTER    char *
52#define VOID_PARAM
53#define void  int
54#endif
55#if HAVE_CONST
56#define constant        const
57#else
58#define constant
59#endif
60
61#define public          /* PUBLIC FUNCTION */
62
63/* Library function declarations */
64
65#if HAVE_SYS_TYPES_H
66#include <sys/types.h>
67#endif
68#if HAVE_STDIO_H
69#include <stdio.h>
70#endif
71#if HAVE_FCNTL_H
72#include <fcntl.h>
73#endif
74#if HAVE_UNISTD_H
75#include <unistd.h>
76#endif
77#if HAVE_CTYPE_H
78#include <ctype.h>
79#endif
80#if HAVE_WCTYPE_H
81#include <wctype.h>
82#endif
83#if HAVE_LIMITS_H
84#include <limits.h>
85#endif
86#if HAVE_STDLIB_H
87#include <stdlib.h>
88#endif
89#if HAVE_STRING_H
90#include <string.h>
91#endif
92
93/* OS-specific includes */
94#ifdef _OSK
95#include <modes.h>
96#include <strings.h>
97#endif
98
99#ifdef __TANDEM
100#include <floss.h>
101#endif
102
103#if MSDOS_COMPILER==WIN32C || OS2
104#include <io.h>
105#endif
106
107#if MSDOS_COMPILER==DJGPPC
108#include <io.h>
109#include <sys/exceptn.h>
110#include <conio.h>
111#include <pc.h>
112#endif
113
114#if !HAVE_STDLIB_H
115char *getenv();
116off_t lseek();
117VOID_POINTER calloc();
118void free();
119#endif
120
121/*
122 * Simple lowercase test which can be used during option processing
123 * (before options are parsed which might tell us what charset to use).
124 */
125#define ASCII_IS_UPPER(c)       ((c) >= 'A' && (c) <= 'Z')
126#define ASCII_IS_LOWER(c)       ((c) >= 'a' && (c) <= 'z')
127#define ASCII_TO_UPPER(c)       ((c) - 'a' + 'A')
128#define ASCII_TO_LOWER(c)       ((c) - 'A' + 'a')
129
130#undef IS_UPPER
131#undef IS_LOWER
132#undef TO_UPPER
133#undef TO_LOWER
134#undef IS_SPACE
135#undef IS_DIGIT
136
137#if HAVE_WCTYPE
138#define IS_UPPER(c)     iswupper(c)
139#define IS_LOWER(c)     iswlower(c)
140#define TO_UPPER(c)     towupper(c)
141#define TO_LOWER(c)     towlower(c)
142#else
143#if HAVE_UPPER_LOWER
144#define IS_UPPER(c)     isupper((unsigned char) (c))
145#define IS_LOWER(c)     islower((unsigned char) (c))
146#define TO_UPPER(c)     toupper((unsigned char) (c))
147#define TO_LOWER(c)     tolower((unsigned char) (c))
148#else
149#define IS_UPPER(c)     ASCII_IS_UPPER(c)
150#define IS_LOWER(c)     ASCII_IS_LOWER(c)
151#define TO_UPPER(c)     ASCII_TO_UPPER(c)
152#define TO_LOWER(c)     ASCII_TO_LOWER(c)
153#endif
154#endif
155
156#ifdef isspace
157#define IS_SPACE(c)     isspace((unsigned char)(c))
158#else
159#define IS_SPACE(c)     ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == '\f')
160#endif
161
162#ifdef isdigit
163#define IS_DIGIT(c)     isdigit((unsigned char)(c))
164#else
165#define IS_DIGIT(c)     ((c) >= '0' && (c) <= '9')
166#endif
167
168#define IS_CSI_START(c) (((LWCHAR)(c)) == ESC || (((LWCHAR)(c)) == CSI))
169
170#ifndef NULL
171#define NULL    0
172#endif
173
174#ifndef TRUE
175#define TRUE            1
176#endif
177#ifndef FALSE
178#define FALSE           0
179#endif
180
181#define OPT_OFF         0
182#define OPT_ON          1
183#define OPT_ONPLUS      2
184
185#if !HAVE_MEMCPY
186#ifndef memcpy
187#define memcpy(to,from,len)     bcopy((from),(to),(len))
188#endif
189#endif
190
191#if HAVE_SNPRINTF
192#define SNPRINTF1(str, size, fmt, v1)             snprintf((str), (size), (fmt), (v1))
193#define SNPRINTF2(str, size, fmt, v1, v2)         snprintf((str), (size), (fmt), (v1), (v2))
194#define SNPRINTF3(str, size, fmt, v1, v2, v3)     snprintf((str), (size), (fmt), (v1), (v2), (v3))
195#define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) snprintf((str), (size), (fmt), (v1), (v2), (v3), (v4))
196#else
197/* Use unsafe sprintf if we don't have snprintf. */
198#define SNPRINTF1(str, size, fmt, v1)             sprintf((str), (fmt), (v1))
199#define SNPRINTF2(str, size, fmt, v1, v2)         sprintf((str), (fmt), (v1), (v2))
200#define SNPRINTF3(str, size, fmt, v1, v2, v3)     sprintf((str), (fmt), (v1), (v2), (v3))
201#define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) sprintf((str), (fmt), (v1), (v2), (v3), (v4))
202#endif
203
204#define BAD_LSEEK       ((off_t)-1)
205
206#ifndef SEEK_SET
207#define SEEK_SET 0
208#endif
209#ifndef SEEK_END
210#define SEEK_END 2
211#endif
212
213#ifndef CHAR_BIT
214#define CHAR_BIT 8
215#endif
216
217/*
218 * Upper bound on the string length of an integer converted to string.
219 * 302 / 1000 is ceil (log10 (2.0)).  Subtract 1 for the sign bit;
220 * add 1 for integer division truncation; add 1 more for a minus sign.
221 */
222#define INT_STRLEN_BOUND(t) ((sizeof(t) * CHAR_BIT - 1) * 302 / 1000 + 1 + 1)
223
224/*
225 * Special types and constants.
226 */
227typedef unsigned long LWCHAR;
228typedef off_t           POSITION;
229typedef off_t           LINENUM;
230#define MIN_LINENUM_WIDTH   7   /* Default min printing width of a line number */
231#define MAX_LINENUM_WIDTH   16  /* Max width of a line number */
232#define MAX_STATUSCOL_WIDTH 4   /* Max width of the status column */
233#define MAX_UTF_CHAR_LEN    6   /* Max bytes in one UTF-8 char */
234
235#define NULL_POSITION   ((POSITION)(-1))
236
237/*
238 * Flags for open()
239 */
240#if MSDOS_COMPILER || OS2
241#define OPEN_READ       (O_RDONLY|O_BINARY)
242#else
243#ifdef _OSK
244#define OPEN_READ       (S_IREAD)
245#else
246#ifdef O_RDONLY
247#define OPEN_READ       (O_RDONLY)
248#else
249#define OPEN_READ       (0)
250#endif
251#endif
252#endif
253
254#if defined(O_WRONLY) && defined(O_APPEND)
255#define OPEN_APPEND     (O_APPEND|O_WRONLY)
256#else
257#ifdef _OSK
258#define OPEN_APPEND     (S_IWRITE)
259#else
260#define OPEN_APPEND     (1)
261#endif
262#endif
263
264/*
265 * Set a file descriptor to binary mode.
266 */
267#if MSDOS_COMPILER==MSOFTC
268#define SET_BINARY(f)   _setmode(f, _O_BINARY);
269#else
270#if MSDOS_COMPILER || OS2
271#define SET_BINARY(f)   setmode(f, O_BINARY)
272#else
273#define SET_BINARY(f)
274#endif
275#endif
276
277/*
278 * Does the shell treat "?" as a metacharacter?
279 */
280#if MSDOS_COMPILER || OS2 || _OSK
281#define SHELL_META_QUEST 0
282#else
283#define SHELL_META_QUEST 1
284#endif
285
286#define SPACES_IN_FILENAMES 1
287
288/*
289 * An IFILE represents an input file.
290 */
291#define IFILE           VOID_POINTER
292#define NULL_IFILE      ((IFILE)NULL)
293
294/*
295 * The structure used to represent a "screen position".
296 * This consists of a file position, and a screen line number.
297 * The meaning is that the line starting at the given file
298 * position is displayed on the ln-th line of the screen.
299 * (Screen lines before ln are empty.)
300 */
301struct scrpos
302{
303        POSITION pos;
304        int ln;
305};
306
307typedef union parg
308{
309        char *p_string;
310        int p_int;
311        LINENUM p_linenum;
312        char p_char;
313} PARG;
314
315#define NULL_PARG       ((PARG *)NULL)
316
317struct textlist
318{
319        char *string;
320        char *endstring;
321};
322
323struct wchar_range
324{
325        LWCHAR first, last;
326};
327
328struct wchar_range_table
329{
330        struct wchar_range *table;
331        int count;
332};
333
334#define EOI             (-1)
335
336#define READ_INTR       (-2)
337
338/* A fraction is represented by an int n; the fraction is n/NUM_FRAC_DENOM */
339#define NUM_FRAC_DENOM                  1000000
340#define NUM_LOG_FRAC_DENOM              6
341
342/* How quiet should we be? */
343#define NOT_QUIET       0       /* Ring bell at eof and for errors */
344#define LITTLE_QUIET    1       /* Ring bell only for errors */
345#define VERY_QUIET      2       /* Never ring bell */
346
347/* How should we prompt? */
348#define PR_SHORT        0       /* Prompt with colon */
349#define PR_MEDIUM       1       /* Prompt with message */
350#define PR_LONG         2       /* Prompt with longer message */
351
352/* How should we handle backspaces? */
353#define BS_SPECIAL      0       /* Do special things for underlining and bold */
354#define BS_NORMAL       1       /* \b treated as normal char; actually output */
355#define BS_CONTROL      2       /* \b treated as control char; prints as ^H */
356
357/* How should we search? */
358#define SRCH_FORW       (1 << 0)  /* Search forward from current position */
359#define SRCH_BACK       (1 << 1)  /* Search backward from current position */
360#define SRCH_NO_MOVE    (1 << 2)  /* Highlight, but don't move */
361#define SRCH_INCR       (1 << 3)  /* Incremental search */
362#define SRCH_FIND_ALL   (1 << 4)  /* Find and highlight all matches */
363#define SRCH_NO_MATCH   (1 << 8)  /* Search for non-matching lines */
364#define SRCH_PAST_EOF   (1 << 9)  /* Search past end-of-file, into next file */
365#define SRCH_FIRST_FILE (1 << 10) /* Search starting at the first file */
366#define SRCH_NO_REGEX   (1 << 12) /* Don't use regular expressions */
367#define SRCH_FILTER     (1 << 13) /* Search is for '&' (filter) command */
368#define SRCH_AFTER_TARGET (1 << 14) /* Start search after the target line */
369#define SRCH_WRAP       (1 << 15) /* Wrap-around search (continue at BOF/EOF) */
370
371#define SRCH_REVERSE(t) (((t) & SRCH_FORW) ? \
372                                (((t) & ~SRCH_FORW) | SRCH_BACK) : \
373                                (((t) & ~SRCH_BACK) | SRCH_FORW))
374
375/* */
376#define NO_MCA          0
377#define MCA_DONE        1
378#define MCA_MORE        2
379
380#define CC_OK           0       /* Char was accepted & processed */
381#define CC_QUIT         1       /* Char was a request to abort current cmd */
382#define CC_ERROR        2       /* Char could not be accepted due to error */
383#define CC_PASS         3       /* Char was rejected (internal) */
384
385#define CF_QUIT_ON_ERASE 0001   /* Abort cmd if its entirely erased */
386
387/* Special char bit-flags used to tell put_line() to do something special */
388#define AT_NORMAL       (0)
389#define AT_UNDERLINE    (1 << 0)
390#define AT_BOLD         (1 << 1)
391#define AT_BLINK        (1 << 2)
392#define AT_STANDOUT     (1 << 3)
393#define AT_ANSI         (1 << 4)  /* Content-supplied "ANSI" escape sequence */
394#define AT_BINARY       (1 << 5)  /* LESS*BINFMT representation */
395#define AT_HILITE       (1 << 6)  /* Internal highlights (e.g., for search) */
396
397#define AT_COLOR_SHIFT    8
398#define AT_NUM_COLORS     16
399#define AT_COLOR          ((AT_NUM_COLORS-1) << AT_COLOR_SHIFT)
400#define AT_COLOR_ATTN     (1 << AT_COLOR_SHIFT)
401#define AT_COLOR_BIN      (2 << AT_COLOR_SHIFT)
402#define AT_COLOR_CTRL     (3 << AT_COLOR_SHIFT)
403#define AT_COLOR_ERROR    (4 << AT_COLOR_SHIFT)
404#define AT_COLOR_LINENUM  (5 << AT_COLOR_SHIFT)
405#define AT_COLOR_MARK     (6 << AT_COLOR_SHIFT)
406#define AT_COLOR_PROMPT   (7 << AT_COLOR_SHIFT)
407#define AT_COLOR_RSCROLL  (8 << AT_COLOR_SHIFT)
408#define AT_COLOR_SEARCH   (9 << AT_COLOR_SHIFT)
409
410typedef enum { CT_NULL, CT_4BIT, CT_6BIT } COLOR_TYPE;
411
412typedef enum {
413	CV_BLUE     = 1,
414	CV_GREEN    = 2,
415	CV_RED      = 4,
416	CV_BRIGHT   = 8,
417	CV_NOCHANGE = -2,
418	CV_ERROR    = -1
419} COLOR_VALUE;
420
421/* ANSI states */
422#define ANSI_MID    1
423#define ANSI_ERR    2
424#define ANSI_END    3
425
426#if '0' == 240
427#define IS_EBCDIC_HOST 1
428#endif
429
430#if IS_EBCDIC_HOST
431/*
432 * Long definition for EBCDIC.
433 * Since the argument is usually a constant, this macro normally compiles
434 * into a constant.
435 */
436#define CONTROL(c) ( \
437        (c)=='[' ? '\047' : \
438        (c)=='a' ? '\001' : \
439        (c)=='b' ? '\002' : \
440        (c)=='c' ? '\003' : \
441        (c)=='d' ? '\067' : \
442        (c)=='e' ? '\055' : \
443        (c)=='f' ? '\056' : \
444        (c)=='g' ? '\057' : \
445        (c)=='h' ? '\026' : \
446        (c)=='i' ? '\005' : \
447        (c)=='j' ? '\025' : \
448        (c)=='k' ? '\013' : \
449        (c)=='l' ? '\014' : \
450        (c)=='m' ? '\015' : \
451        (c)=='n' ? '\016' : \
452        (c)=='o' ? '\017' : \
453        (c)=='p' ? '\020' : \
454        (c)=='q' ? '\021' : \
455        (c)=='r' ? '\022' : \
456        (c)=='s' ? '\023' : \
457        (c)=='t' ? '\074' : \
458        (c)=='u' ? '\075' : \
459        (c)=='v' ? '\062' : \
460        (c)=='w' ? '\046' : \
461        (c)=='x' ? '\030' : \
462        (c)=='y' ? '\031' : \
463        (c)=='z' ? '\077' : \
464        (c)=='A' ? '\001' : \
465        (c)=='B' ? '\002' : \
466        (c)=='C' ? '\003' : \
467        (c)=='D' ? '\067' : \
468        (c)=='E' ? '\055' : \
469        (c)=='F' ? '\056' : \
470        (c)=='G' ? '\057' : \
471        (c)=='H' ? '\026' : \
472        (c)=='I' ? '\005' : \
473        (c)=='J' ? '\025' : \
474        (c)=='K' ? '\013' : \
475        (c)=='L' ? '\014' : \
476        (c)=='M' ? '\015' : \
477        (c)=='N' ? '\016' : \
478        (c)=='O' ? '\017' : \
479        (c)=='P' ? '\020' : \
480        (c)=='Q' ? '\021' : \
481        (c)=='R' ? '\022' : \
482        (c)=='S' ? '\023' : \
483        (c)=='T' ? '\074' : \
484        (c)=='U' ? '\075' : \
485        (c)=='V' ? '\062' : \
486        (c)=='W' ? '\046' : \
487        (c)=='X' ? '\030' : \
488        (c)=='Y' ? '\031' : \
489        (c)=='Z' ? '\077' : \
490        (c)=='|' ? '\031' : \
491        (c)=='\\' ? '\034' : \
492        (c)=='^' ? '\036' : \
493        (c)&077)
494#else
495#define CONTROL(c)      ((c)&037)
496#endif /* IS_EBCDIC_HOST */
497
498#define ESC             CONTROL('[')
499#define ESCS            "\33"
500#define CSI             ((unsigned char)'\233')
501#define CHAR_END_COMMAND 0x40000000
502
503#if _OSK_MWC32
504#define LSIGNAL(sig,func)       os9_signal(sig,func)
505#else
506#define LSIGNAL(sig,func)       signal(sig,func)
507#endif
508
509#if HAVE_SIGPROCMASK
510#if HAVE_SIGSET_T
511#else
512#undef HAVE_SIGPROCMASK
513#endif
514#endif
515#if HAVE_SIGPROCMASK
516#if HAVE_SIGEMPTYSET
517#else
518#undef  sigemptyset
519#define sigemptyset(mp) *(mp) = 0
520#endif
521#endif
522
523#define S_INTERRUPT     01
524#define S_STOP          02
525#define S_WINCH         04
526#define ABORT_SIGS()    (sigs & (S_INTERRUPT|S_STOP))
527
528#define QUIT_OK         0
529#define QUIT_ERROR      1
530#define QUIT_INTERRUPT  2
531#define QUIT_SAVED_STATUS (-1)
532
533#define FOLLOW_DESC     0
534#define FOLLOW_NAME     1
535
536/* filestate flags */
537#define CH_CANSEEK      001
538#define CH_KEEPOPEN     002
539#define CH_POPENED      004
540#define CH_HELPFILE     010
541#define CH_NODATA       020     /* Special case for zero length files */
542
543#define ch_zero()       ((POSITION)0)
544
545#define FAKE_HELPFILE   "@/\\less/\\help/\\file/\\@"
546#define FAKE_EMPTYFILE  "@/\\less/\\empty/\\file/\\@"
547
548/* Flags for cvt_text */
549#define CVT_TO_LC       01      /* Convert upper-case to lower-case */
550#define CVT_BS          02      /* Do backspace processing */
551#define CVT_CRLF        04      /* Remove CR after LF */
552#define CVT_ANSI        010     /* Remove ANSI escape sequences */
553
554#if HAVE_TIME_T
555#define time_type       time_t
556#else
557#define time_type       long
558#endif
559
560/* X11 mouse reporting definitions */
561#define X11MOUSE_BUTTON1    0 /* Left button press */
562#define X11MOUSE_BUTTON2    1 /* Middle button press */
563#define X11MOUSE_BUTTON3    2 /* Right button press */
564#define X11MOUSE_BUTTON_REL 3 /* Button release */
565#define X11MOUSE_WHEEL_UP   0x40 /* Wheel scroll up */
566#define X11MOUSE_WHEEL_DOWN 0x41 /* Wheel scroll down */
567#define X11MOUSE_OFFSET     0x20 /* Added to button & pos bytes to create a char */
568
569struct mlist;
570struct loption;
571struct hilite_tree;
572struct ansi_state;
573#include "pattern.h"
574#include "funcs.h"
575
576/* Functions not included in funcs.h */
577void postoa LESSPARAMS ((POSITION, char*));
578void linenumtoa LESSPARAMS ((LINENUM, char*));
579void inttoa LESSPARAMS ((int, char*));
580int lstrtoi LESSPARAMS ((char*, char**));
581POSITION lstrtopos LESSPARAMS ((char*, char**));
582#if MSDOS_COMPILER==WIN32C
583int pclose LESSPARAMS ((FILE*));
584#endif
585