2 * Copyright (C) 1984-2023 Mark Nudelman
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.
7 * For more information, see the README file.
12 * Entry point, initialization, miscellaneous routines.
16 #if MSDOS_COMPILER==WIN32C
17 #define WIN32_LEAN_AND_MEAN
21 public char * every_first_cmd
= NULL
;
24 public IFILE curr_ifile
= NULL_IFILE
;
25 public IFILE old_ifile
= NULL_IFILE
;
26 public struct scrpos initial_scrpos
;
27 public POSITION start_attnpos
= NULL_POSITION
;
28 public POSITION end_attnpos
= NULL_POSITION
;
30 public char * progname
;
36 public int logfile
= -1;
37 public int force_logfile
= FALSE
;
38 public char * namelogfile
= NULL
;
43 public char * editproto
;
48 extern char * tagoption
;
49 extern int jump_sline
;
53 static char consoleTitle
[256];
56 public int one_screen
;
57 extern int less_is_more
;
58 extern int missing_cap
;
61 extern int quit_if_one_screen
;
64 extern int redraw_on_quit
;
65 extern int term_init_done
;
66 extern int first_time
;
71 int main(int argc
, char *argv
[])
77 _response(&argc
, &argv
);
78 _wildcard(&argc
, &argv
);
88 s
= lgetenv("LESSSECURE");
94 if (getenv("HOME") == NULL
)
97 * If there is no HOME environment variable,
98 * try the concatenation of HOMEDRIVE + HOMEPATH.
100 char *drive
= getenv("HOMEDRIVE");
101 char *path
= getenv("HOMEPATH");
102 if (drive
!= NULL
&& path
!= NULL
)
104 char *env
= (char *) ecalloc(strlen(drive
) +
105 strlen(path
) + 6, sizeof(char));
106 strcpy(env
, "HOME=");
112 GetConsoleTitle(consoleTitle
, sizeof(consoleTitle
)/sizeof(char));
116 * Process command line arguments and LESS environment arguments.
117 * Command line arguments override environment arguments.
131 * If the name of the executable program is "more",
132 * act like LESS_IS_MORE is set.
134 s
= last_component(progname
);
135 if (strcmp(s
, "more") == 0)
140 s
= lgetenv(less_is_more
? "MORE" : "LESS");
144 #define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
145 while (argc
> 0 && (isoptstring(*argv
) || isoptpending()))
149 if (strcmp(s
, "--") == 0)
158 * Last command line option was a flag requiring a
159 * following string, but there was no following string.
168 editor
= lgetenv("VISUAL");
169 if (editor
== NULL
|| *editor
== '\0')
171 editor
= lgetenv("EDITOR");
172 if (isnullenv(editor
))
175 editproto
= lgetenv("LESSEDIT");
176 if (isnullenv(editproto
))
177 editproto
= "%E ?lm+%lm. %g";
181 * Call get_ifile with all the command line filenames
182 * to "register" them with the ifile system.
186 ifile
= get_ifile(FAKE_HELPFILE
, ifile
);
189 #if (MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC)
191 * Because the "shell" doesn't expand filename patterns,
192 * treat each argument as a filename pattern rather than
194 * Expand the pattern and iterate over the expanded list.
196 struct textlist tlist
;
201 gfilename
= lglob(*argv
++);
202 init_textlist(&tlist
, gfilename
);
204 while ((filename
= forw_textlist(&tlist
, filename
)) != NULL
)
206 qfilename
= shell_unquote(filename
);
207 (void) get_ifile(qfilename
, ifile
);
209 ifile
= prev_ifile(NULL_IFILE
);
213 (void) get_ifile(*argv
++, ifile
);
214 ifile
= prev_ifile(NULL_IFILE
);
218 * Set up terminal, etc.
223 * Output is not a tty.
224 * Just copy the input file(s) to output.
226 set_output(1); /* write to stdout */
228 if (edit_first() == 0)
232 } while (edit_next(1) == 0);
237 if (missing_cap
&& !know_dumb
)
238 error("WARNING: terminal is not fully functional", NULL_PARG
);
244 * Select the first file to examine.
247 if (tagoption
!= NULL
|| strcmp(tags
, "-") == 0)
250 * A -t option was given.
251 * Verify that no filenames were also given.
252 * Edit the file selected by the "tags" search,
253 * and search for the proper line in the file.
257 error("No filenames allowed with -t option", NULL_PARG
);
261 if (edit_tagfile()) /* Edit file which contains the tag */
264 * Search for the line which contains the tag.
265 * Set up initial_scrpos so we display that line.
267 initial_scrpos
.pos
= tagsearch();
268 if (initial_scrpos
.pos
== NULL_POSITION
)
270 initial_scrpos
.ln
= jump_sline
;
277 * See if file fits on one screen to decide whether
278 * to send terminal init. But don't need this
279 * if -X (no_init) overrides this (see init()).
281 if (quit_if_one_screen
)
283 if (nifile() > 1) /* If more than one file, -F cannot be used */
284 quit_if_one_screen
= FALSE
;
286 one_screen
= get_one_screen();
293 * We displayed some messages on error output
294 * (file descriptor 2; see flush()).
295 * Before erasing the screen contents, wait for a keystroke.
297 less_printf("Press RETURN to continue ", NULL_PARG
);
310 * Copy a string to a "safe" place
311 * (that is, to a buffer allocated by calloc).
313 public char * save(constant
char *s
)
317 p
= (char *) ecalloc(strlen(s
)+1, sizeof(char));
322 public void out_of_memory(void)
324 error("Cannot allocate memory", NULL_PARG
);
330 * Like calloc(), but never returns an error (NULL).
332 public void * ecalloc(int count
, unsigned int size
)
336 p
= (void *) calloc(count
, size
);
343 * Skip leading spaces in a string.
345 public char * skipsp(char *s
)
347 while (*s
== ' ' || *s
== '\t')
353 * See how many characters of two strings are identical.
354 * If uppercase is true, the first string must begin with an uppercase
355 * character; the remainder of the first string may be either case.
357 public int sprefix(char *ps
, char *s
, int uppercase
)
363 for ( ; *s
!= '\0'; s
++, ps
++)
368 if (len
== 0 && ASCII_IS_LOWER(c
))
370 if (ASCII_IS_UPPER(c
))
371 c
= ASCII_TO_LOWER(c
);
374 if (len
> 0 && ASCII_IS_UPPER(sc
))
375 sc
= ASCII_TO_LOWER(sc
);
386 public void quit(int status
)
388 static int save_status
;
391 * Put cursor at bottom left corner, clear the line,
392 * reset the terminal modes, and exit.
395 status
= save_status
;
397 save_status
= status
;
399 check_altpipe_error();
404 if (redraw_on_quit
&& term_init_done
)
407 * The last file text displayed might have been on an
408 * alternate screen, which now (since deinit) cannot be seen.
409 * redraw_on_quit tells us to redraw it on the main screen.
411 first_time
= 1; /* Don't print "skipping" or tildes */
418 #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
420 * If we don't close 2, we get some garbage from
421 * 2's buffer when it flushes automatically.
422 * I cannot track this one down RB
423 * The same bug shows up if we use ^C^C to abort.
428 SetConsoleTitle(consoleTitle
);