Annotation of libwww/LineMode/src/HTBrowse.c, revision 1.28
1.1 timbl 1: /* HyperText Browser for Dumb Terminals HTBrowse.c
2: ** ====================================
3: **
4: ** Authors:
5: ** NP: Nicola Pellow Tech.Student CERN 1990-91
6: ** TBL: Tim Berners-Lee CERN (timbl@info.cern.ch)
7: ** JFG: Jean-Francois Groff, Cooperant CERN 1991-92 (jfg@info.cern.ch)
8: ** DR: Dudu Rashty +972-2-584848 <RASHTY@hujivms.bitnet>
1.8 duns 9: ** MD: Mark Donszelmann, DELPHI CERN, (duns@vxdeop.cern.ch)
1.1 timbl 10: **
11: ** Copyright CERN 1990-1992 See Copyright.html
12: **
13: ** History:
14: **
15: ** 4 Dec 90: Written from scratch (NP)
16: ** 11 Feb 91: Code written by TBL so that the browser could be linked with
17: ** code produced by Bernd Pollermann, enabling access to the
18: ** data on CERNVM. This involved changing the code to handle file
19: ** numbers rather than file pointers.
20: ** 18 Mar 91: The feature of history mechanism was included, enabling a
21: ** record of previous nodes visited to be kept.
22: ** 6 Apr 91: When a node is accessed, it is immediately read into a
23: ** buffer, in an unformatted state, as soon as the connection is
24: ** made, so that the server is freed as quickly as possible.
25: ** The program now also uses the additional modules HTBufferFile.c
26: ** and HTBufferFile.h.
27: ** 17 Apr 91: Can be used on machines running ANSI C and ordinary C.
28: ** 10 May 91: Formatted text is stored in a linked list buffer which allows
29: ** scrolling and better page breaks in the middle of text.
30: ** Code incorporated by Tim BL, to enable anonymous FTP.
31: ** 21 May 91: Accepts various parameters on the command line.
32: ** 19 Aug 91: Currently available in Unix, VAX/VMS and MVS environments.
33: ** 21 Nov 91: Character grid uses new architecture. (TBL)
34: ** added -w option, new commands, print,
35: ** ... See Features.html for further details
36: ** 16 Jan 92: Put in VIOLA-compatible options - see \017 characters.
37: ** \017 and \016 bracket user-selectable input.
38: ** 27 Feb 92: New handling of user input, enhanced command syntax. (JFG)
39: ** 18 May 92: PS command see ifdef SLAVE_PRINTER (DR/TBL)
40: ** 6 Oct 92: Painful recovery from someone(?)'s attept to pretty print.(TBL)
41: ** Please see coding style guide before changing indentation etc!
42: ** Mar 93: Force on HTFile's HTDirAccess and HTDirReadme flags.
1.8 duns 43: ** 3 Nov 93: (MD) Changed vms into VMS
44: ** (MD) Assigne output in main, not at initialize (VMS only)
1.1 timbl 45: **
46: ** Compilation-time macro options
47: **
48: ** REF_MARK Printf string to be used for printing anchor numbers
49: ** END_MARK String to be used to denote the end of a document
50: ** VL Version number, quoted eg "1.2a"
51: */
52: #ifndef VL
53: #define VL "unspecified"
54: #endif
55:
1.12 frystyk 56: /* If the guy gives the "MANUAL" command, jump to this: */
1.1 timbl 57: #ifndef MANUAL
1.13 frystyk 58: #define MANUAL "http://info.cern.ch/hypertext/WWW/LineMode/Defaults/QuickGuide.html"
1.12 frystyk 59: #endif
60:
1.26 frystyk 61: #ifndef COM_HELP_FILE
62: #define COM_HELP_FILE "http://info.cern.ch/hypertext/WWW/LineMode/Defaults/CommandLine.html"
63: #endif
64:
1.12 frystyk 65: #ifndef DEFAULT_LOCAL_LOGFILE
1.13 frystyk 66: #define DEFAULT_LOCAL_LOGFILE "WWW-log" /* Log file name for local execution */
1.12 frystyk 67: #endif
68:
69: #ifndef DEFAULT_OUTPUT_FILE
1.13 frystyk 70: #define DEFAULT_OUTPUT_FILE "WWW-out" /* Output file name for non-interactive run */
1.12 frystyk 71: #endif
72:
73: #ifndef DEFAULT_REF_HEAD
1.13 frystyk 74: #define DEFAULT_REF_HEAD "*** References from this document ***"
1.12 frystyk 75: #endif
76:
1.1 timbl 77: /* Check Statements */
78: /* ================ */
79:
1.12 frystyk 80: #define NAME_CHECK 0 /* Trace to show NAME anchors */
81: /* #define LONG_PROMPT 1 */ /* Long or short user prompt */
1.1 timbl 82:
83:
84: /* Include Files */
85: /* ============= */
86:
87: #include <ctype.h>
1.11 frystyk 88: #include "HTUtils.h" /* WWW general purpose macros */
1.1 timbl 89:
1.11 frystyk 90: #include "HTBrowse.h" /* Things exported, short names */
1.1 timbl 91:
1.11 frystyk 92: #include "GridText.h" /* Hypertext definition */
1.1 timbl 93:
94: #include "HTFormat.h"
95: #include "HTTCP.h" /* TCP/IP utilities */
96: #include "HTAnchor.h" /* Anchor class */
97: #include "HTParse.h" /* WWW address manipulation */
98: #include "HTAccess.h" /* WWW document access network code */
99: #include "HTHistory.h" /* Navigational aids */
100: #include "HTML.h" /* For parser */
101: #include "HTFWriter.h" /* For non-interactive output */
102: #include "HTFile.h" /* For Dir access flags */
1.3 timbl 103: #include "HTRules.h" /* For loading rule file */
1.1 timbl 104:
105: #ifdef THINK_C /* Macintosh Think C development system */
106: #include <console.h>
107: #include <time.h>
108: extern int socketdebug; /* Must be declared in the socket library */
109: #endif
110:
111: extern HTStyleSheet * styleSheet;
112:
113: /* Define Statements */
114: /* ================= */
115:
116: #ifndef REF_MARK /* May be redefined on command line */
117: #ifdef VIOLA
118: #define REF_MARK "[\017%d\016]" /* Shift-in, shift-out around number */
119: #define PROMPT_MARK "\017%s\016"
120: #else
121: #define PROMPT_MARK "%s"
122: #ifdef VM
123: #define REF_MARK " <%d>" /* IBM terminals can't handle [] well */
124: #else
125: #define REF_MARK "[%d]"
126: #endif
127: #endif
128: #endif
129:
130: #ifndef END_MARK
131: #ifdef VM
132: #define END_MARK " <End>"
133: #else
134: #define END_MARK " [End]"
135: #endif
136: #endif
137:
138: #ifndef EOF
139: #define EOF (-1) /* End of file character defined as -1 */
140: #endif
141:
142:
143: #ifdef NEWLIB
1.13 frystyk 144: #define SCREEN_WIDTH 78
1.1 timbl 145: #endif
146:
147: #ifndef SCREEN_WIDTH
1.13 frystyk 148: #define SCREEN_WIDTH 79 /* Default width of the screen */
1.1 timbl 149: #endif
1.13 frystyk 150:
151: #ifndef MIN_SCREEN_WIDTH
152: #define MIN_SCREEN_WIDTH 10
153: #endif
154:
155: #ifndef MAX_SCREEN_WIDTH
156: #define MAX_SCREEN_WIDTH 150
157: #endif
158:
1.1 timbl 159: #ifndef SCREEN_HEIGHT
1.13 frystyk 160: #define SCREEN_HEIGHT 24 /* Default number of lines to the screen */
161: #endif
162:
163: #ifndef MIN_SCREEN_HEIGHT
164: #define MIN_SCREEN_HEIGHT 5
165: #endif
166:
167: #ifndef MAX_SCREEN_HEIGHT
1.14 frystyk 168: #define MAX_SCREEN_HEIGHT 200
1.1 timbl 169: #endif
170:
171: #ifdef VM /* Needed to flush out the prompt line..*/
172: #ifndef NEWLIB /* except on NEWLIB which can wrap. */
173: #define NEWLINE_PROMPT /* before input */
174: #endif
175: #endif
176:
1.16 frystyk 177: #define INFINITY 1024 /*!! BUG*/
178: #define ADDRESS_LENGTH INFINITY /* Maximum address length of node */
1.12 frystyk 179: #define TITLE_LENGTH INFINITY /* Maximum length of a title */
1.16 frystyk 180: #define RESPONSE_LENGTH INFINITY /* Maximum length of users response */
181:
182: #ifndef MAXPATHLEN
183: #define NO_GETWD /* Assume no getwd() if no MAXPATHLEN */
184: #else
185: extern char * getwd();
186: #endif
187:
188: #ifdef HAS_GETCWD /* May be defined on command line */
189: extern char * getcwd();
190: #endif
191:
192: #ifndef NO_GETPID /* May be defined from command line */
193: extern int getpid();
194: #endif
1.1 timbl 195:
196: /* Public Variables
197: ** ================
198: */
199:
1.18 frystyk 200: PUBLIC char * HTAppName = "CERN-LineMode"; /* Application name */
201: PUBLIC char * HTAppVersion = VL; /* Application version */
202: PUBLIC int HTScreenWidth = SCREEN_WIDTH; /* By default */
203: PUBLIC int HTScreenHeight = -1; /* Undefined */
204: PUBLIC BOOL display_anchors = YES; /* anchor will be shown in text? */
205: PUBLIC char * log_file_name = 0; /* Root of log file name */
1.2 timbl 206:
1.19 frystyk 207: #ifdef OLD_CODE
1.17 duns 208: #ifdef VMS
209: PUBLIC BOOL interactive = YES; /* e.g. shows prompts etc */
210: #else /* not VMS */
1.14 frystyk 211: PRIVATE BOOL interactive = YES; /* e.g. shows prompts etc */
1.17 duns 212: #endif /* not VMS */
1.19 frystyk 213: #endif /* OLD_CODE */
1.1 timbl 214:
1.16 frystyk 215: PUBLIC char * start_reference = NULL; /* Format string for start anchor */
1.18 frystyk 216: PUBLIC char * end_reference = REF_MARK; /* for end anchor */
217: PUBLIC char * reference_mark = "[%d] "; /* for reference lists */
218: PUBLIC char * end_mark = END_MARK; /* Format string for [End] */
1.1 timbl 219:
220: /* Moved into other files: */
221:
222: /* PUBLIC char * HTClientHost = 0; HTAccess */
223: /* PUBLIC int WWW_TraceFlag = 0; HTString */
224: /* PUBLIC FILE * logfile = 0; HTAccess */
225:
226: /* Private variables
227: ** =================
228: */
229: /* Arrays for storing the HyperText References */
230:
1.18 frystyk 231: PRIVATE HTParentAnchor * home_anchor = NULL; /* First document anchor */
232: PRIVATE char keywords[ADDRESS_LENGTH]; /* Search terms from command line */
233: PRIVATE char * output_file_name = NULL; /* -o xxxx */
1.1 timbl 234: PRIVATE char choice[RESPONSE_LENGTH]; /* Users response */
1.18 frystyk 235: PRIVATE char * refhead = DEFAULT_REF_HEAD; /* Reference list heading */
236: PRIVATE char * logfile_root = 0; /* Log file name */
237: PRIVATE BOOL filter=0; /* Load from stdin? */
1.1 timbl 238: PRIVATE BOOL listrefs_option = 0; /* -listrefs option used? */
1.10 frystyk 239: PRIVATE HTRequest * request;
1.18 frystyk 240: PRIVATE BOOL OutSource = NO; /* Output source, YES/NO */
1.1 timbl 241:
1.8 duns 242:
243: #ifdef VMS
244: PRIVATE FILE * output; /* assignment done in main */
1.17 duns 245: #ifdef __DECC
246: /* dummy declarations to make sure that LINKER will not complain */
247: PUBLIC char *HTBinDir;
248: PUBLIC int HTDiag;
249: PUBLIC char *HTPostScript;
250: PUBLIC char *HTPutScript;
251: PUBLIC char *HTSearchScript;
252: #endif /* DECC */
1.8 duns 253: #else /* not VMS */
1.4 timbl 254: PRIVATE FILE * output = stdout;
1.8 duns 255: #endif /* not VMS */
1.4 timbl 256:
1.1 timbl 257: /* Forward Declaration of Functions */
258: /* ================================ */
259:
260: PRIVATE void History_List NOPARAMS;
1.23 frystyk 261: PRIVATE BOOL Selection_Prompt NOPARAMS;
1.1 timbl 262: PRIVATE void Error_Selection NOPARAMS;
263: PRIVATE void help_screen NOPARAMS;
264: PRIVATE void Reference_List PARAMS((BOOL titles));
1.14 frystyk 265: PRIVATE void ErrMsg PARAMS((char *Msg, char *Str));
1.18 frystyk 266: PRIVATE BOOL SaveOutputStream PARAMS((char *This, char *Next));
267:
1.1 timbl 268:
1.7 secret 269: #ifdef ultrix
270: #define GET_SCREEN_SIZE
271: #endif
272:
273: #ifdef __osf__
274: #define GET_SCREEN_SIZE
275: #endif
276:
277: #ifdef GET_SCREEN_SIZE
278: #include <sys/ioctl.h>
279:
280: /*
281: * Get size of the output screen. Stolen from less.
282: */
283: void
284: scrsize(p_height, p_width)
285: int *p_height;
286: int *p_width;
287: {
288: register char *s;
289: int ioctl();
290: struct winsize w;
291:
292: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0)
293: *p_height = w.ws_row;
294: else
295: if ((s = getenv("LINES")) != NULL)
296: *p_height = atoi(s);
297: else
298: *p_height = SCREEN_HEIGHT;
299:
300: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
301: *p_width = w.ws_col;
302: else
303: if ((s = getenv("COLUMNS")) != NULL)
304: *p_width = atoi(s);
305: else
306: *p_width = 80;
307: }
308: #endif /* GET_SCREEN_SIZE, BSN */
309:
310:
1.1 timbl 311: /* MAIN PROGRAM
312: ** ------------
313: */
314:
315: int main
316: #ifdef __STDC__
317: (int argc, char * argv[])
318: #else
319: (argc, argv)
320: int argc;
321: char * argv[];
322: #endif
323:
324: {
1.13 frystyk 325: int return_status = 0;
1.1 timbl 326: int arg; /* Argument number as we scan */
327: BOOL argument_found = NO;
1.12 frystyk 328: BOOL logfile_flag = NO;
1.18 frystyk 329: BOOL interactive = YES; /* Default is interactive mode */
1.1 timbl 330: BOOL first_keyword = YES;
331: char* default_default=0; /* Parse home relative to this */
1.18 frystyk 332: HTFormat input_format = WWW_HTML; /* Used with filter */
1.1 timbl 333:
1.7 secret 334: #if defined(ultrix) || defined(__osf__)
335: int scr_height, scr_width;
336: #endif /* ultrix and OSF/1 */
337:
1.1 timbl 338: #ifdef THINK_C /* command line from Think_C */
339: int i;
340: argc=ccommand(&argv);
341: #endif
1.8 duns 342:
1.9 timbl 343: request = HTRequest_new();
1.13 frystyk 344: /* request->conversions = HTList_new(); Done by HTRequest_new() Henrik 18/02-94 */
1.10 frystyk 345:
1.8 duns 346: #ifdef VMS
347: output = stdout;
348: #endif /* VMS */
1.1 timbl 349:
350: StrAllocCopy(default_default, "file://");
351: StrAllocCat(default_default, HTHostName()); /* eg file://cernvax.cern.ch */
1.7 secret 352:
353: #ifdef GET_SCREEN_SIZE
354: scrsize(&scr_height, &scr_width);
355: HTScreenHeight = scr_height;
356: #endif /* ultrix or OSF/1, BSN */
1.1 timbl 357:
358: #ifndef MAXPATHLEN
359: #define NO_GETWD /* Assume no getwd() if no MAXPATHLEN */
360: #endif
361:
362: #ifdef NO_GETWD /* No getwd() on this machine */
363: #ifdef HAS_GETCWD /* System V variant SIGN CHANGED TBL 921006 !! */
364:
365: {
366: char wd[1024]; /*!! Arbitrary*/
367: char * result = getcwd(wd, sizeof(wd));
368: if (result) {
369:
1.8 duns 370: #ifdef VMS
371: /* convert directory name to Unix-style syntax */
1.1 timbl 372: char * disk = strchr (wd, ':');
373: char * dir = strchr (wd, '[');
374: if (disk) {
375: *disk = '\0';
376: StrAllocCat (default_default, "/"); /* needs delimiter */
377: StrAllocCat (default_default, wd);
378: }
379: if (dir) {
380: char *p;
381: *dir = '/'; /* Convert leading '[' */
382: for (p = dir ; *p != ']'; ++p)
383: if (*p == '.') *p = '/';
384: *p = '\0'; /* Cut on final ']' */
385: StrAllocCat (default_default, dir);
386: }
387: #else /* not VMS */
388: StrAllocCat (default_default, wd);
389: #endif /* not VMS */
390: } else {
1.14 frystyk 391: ErrMsg("Can't read working directory (getcwd)", NULL);
1.1 timbl 392: }
393: } /* end if good getcwd result */
394:
395: #else /* has NO getcwd */
396:
1.14 frystyk 397: ErrMsg("This platform does not support getwd() or getcwd()", NULL);
398:
1.1 timbl 399: #endif /* has no getcwd */
400:
401: #else /* has getwd */
402: {
403: char wd[MAXPATHLEN];
404: char * result = getwd(wd);
405: if (result) {
406: StrAllocCat(default_default, wd);
407: } else {
1.14 frystyk 408: ErrMsg("Can't read working directory.", NULL);
1.1 timbl 409: }
410: }
411: #endif
412:
1.8 duns 413: #ifdef VMS
1.1 timbl 414: StrAllocCat(default_default, "default.html");
415: #else
416: StrAllocCat(default_default, "/default.html");
417: #endif
418:
419: /* Check for command line options
420: ** ------------------------------
421: */
422: keywords[0] = 0; /* Clear string */
423: for (arg=1; arg<argc ; arg++) {
1.14 frystyk 424: if (*argv[arg] == '-') {
425:
426: /* - alone => filter */
427: if (argv[arg][1] == 0) {
428: filter = YES;
1.18 frystyk 429: interactive = NO; /* From stdin, Force non-interactive */
430:
1.26 frystyk 431: /* -? or -help: show the command line help page */
432: } else if (!strcmp(argv[arg], "-?") ||
433: !strcmp(argv[arg], "-help")) {
434: home_anchor = (HTParentAnchor *)
435: HTAnchor_findAddress(COM_HELP_FILE);
436: argument_found = YES; /* Don't try to find other pages */
437:
1.18 frystyk 438: /* from -- Initial represntation (only with filter) */
439: } else if (!strcmp(argv[arg], "-from")) {
440: input_format = (arg+1 >= argc || *argv[arg+1] == '-') ?
441: WWW_HTML : HTAtom_for(argv[++arg]);
1.14 frystyk 442:
1.1 timbl 443: #ifdef TRACE
444: /* Verify: Turns on trace */
1.14 frystyk 445: } else if (!strcmp(argv[arg], "-v")) {
1.1 timbl 446: WWW_TraceFlag = 1;
447: #endif
448:
449: /* Page size */
1.24 frystyk 450: } else if (!strncmp(argv[arg], "-p", 2)) {
1.27 frystyk 451: if (*(argv[arg]+2)) {
452: if (sscanf(argv[arg]+2, "%d", &HTScreenHeight) < 1)
453: HTScreenHeight = -1;
1.25 frystyk 454: else {
455: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
456: HTScreenHeight = MIN_SCREEN_HEIGHT;
457: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
458: HTScreenHeight = MAX_SCREEN_HEIGHT;
459: }
1.27 frystyk 460: } else if (arg+1 < argc && *argv[arg+1] != '-') {
461: if (sscanf(argv[++arg], "%d", &HTScreenHeight) < 1)
462: HTScreenHeight = -1;
1.25 frystyk 463: else {
464: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
465: HTScreenHeight = MIN_SCREEN_HEIGHT;
466: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
467: HTScreenHeight = MAX_SCREEN_HEIGHT;
468: }
1.24 frystyk 469: }
1.13 frystyk 470:
1.1 timbl 471: /* Page width */
1.24 frystyk 472: } else if (!strncmp(argv[arg], "-w", 2)) {
1.27 frystyk 473: if (*(argv[arg]+2)) {
474: if (sscanf(argv[arg]+2, "%d", &HTScreenWidth) < 1)
475: HTScreenWidth = SCREEN_WIDTH;
476: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1.25 frystyk 477: if (sscanf(argv[++arg], "%d", &HTScreenWidth) < 1)
478: HTScreenWidth = SCREEN_WIDTH;
1.27 frystyk 479: }
1.25 frystyk 480: if(HTScreenWidth < MIN_SCREEN_WIDTH)
481: HTScreenWidth = MIN_SCREEN_WIDTH;
482: if(HTScreenWidth > MAX_SCREEN_WIDTH)
483: HTScreenWidth = MAX_SCREEN_WIDTH;
1.12 frystyk 484:
485: /* to -- Final represntation */
1.14 frystyk 486: } else if (!strcmp(argv[arg], "-to")) {
487: request->output_format =
488: (arg+1 >= argc || *argv[arg+1] == '-') ?
1.18 frystyk 489: WWW_PRESENT :
1.14 frystyk 490: HTAtom_for(argv[++arg]);
491: HTOutputSource = YES; /* Turn on shortcut */
492: interactive = NO; /* JFG */
1.1 timbl 493:
494: /* Telnet from */
1.14 frystyk 495: } else if (!strcmp(argv[arg], "-h")) {
1.23 frystyk 496: if (arg+1 < argc && *argv[arg+1] != '-') {
497: HTClientHost = argv[++arg]; /* Use host name */
498: }
499:
1.1 timbl 500: /* Log file */
1.14 frystyk 501: } else if (!strcmp(argv[arg], "-l")) {
502: if (arg+1 < argc && *argv[arg+1] != '-')
503: logfile_root = argv[++arg];
1.12 frystyk 504: logfile_flag = YES;
1.1 timbl 505:
1.12 frystyk 506: /* List References */
1.14 frystyk 507: } else if (!strcmp(argv[arg], "-listrefs")) {
1.1 timbl 508: listrefs_option = YES;
1.14 frystyk 509: interactive = NO; /* non-interactive */
1.1 timbl 510:
511: /* Non-interactive */
1.14 frystyk 512: } else if (!strcmp(argv[arg], "-n")) {
1.1 timbl 513: interactive = NO;
514:
515: /* Output filename */
1.14 frystyk 516: } else if (!strcmp(argv[arg], "-o")) {
517: output_file_name = (arg+1 < argc && *argv[arg+1] != '-') ?
518: argv[++arg] : DEFAULT_OUTPUT_FILE;
1.1 timbl 519: interactive = NO;
1.12 frystyk 520:
1.1 timbl 521: /* Anchor format */
1.14 frystyk 522: } else if (!strcmp(argv[arg], "-a")) {
523: if (arg+1 < argc && *argv[arg+1] != '-')
524: end_reference = argv[++arg]; /* New representation */
1.1 timbl 525:
1.3 timbl 526: /* Anchor format */
1.14 frystyk 527: } else if (!strcmp(argv[arg], "-ar")) {
528: if (arg+1 < argc && *argv[arg+1] != '-')
529: reference_mark = argv[++arg]; /* Change representation */
1.3 timbl 530:
531: /* Anchor format */
1.14 frystyk 532: } else if (!strcmp(argv[arg], "-as")) {
533: if (arg+1 < argc && *argv[arg+1] != '-')
534: start_reference = argv[++arg]; /* Change representation */
1.3 timbl 535:
1.1 timbl 536: /* No anchors */
1.14 frystyk 537: } else if (!strcmp(argv[arg], "-na")) {
1.1 timbl 538: display_anchors = NO;
539:
1.2 timbl 540: #ifndef NO_RULES
1.14 frystyk 541: } else if (!strcmp(argv[arg], "-r")) {
542: if (arg+1 < argc && *argv[arg+1] != '-') {
543: if (HTLoadRules(argv[++arg]) < 0) {
544: ErrMsg("Can't open rule file", argv[arg]);
1.13 frystyk 545: return_status = -1;
546: goto endproc;
547: }
1.2 timbl 548: }
549: #endif
550: #ifndef NO_DIR_OPTIONS
1.14 frystyk 551: } else if (!strncmp(argv[arg], "-d", 2)) {
1.2 timbl 552: char *p = argv[arg]+2;
553: for(;*p;p++) {
554: switch (argv[arg][2]) {
555: case 'b': HTDirReadme = HT_DIR_README_BOTTOM; break;
556: case 'n': HTDirAccess = HT_DIR_FORBID; break;
557: case 'r': HTDirReadme = HT_DIR_README_NONE; break;
558: case 's': HTDirAccess = HT_DIR_SELECTIVE; break;
559: case 't': HTDirReadme = HT_DIR_README_TOP; break;
560: case 'y': HTDirAccess = HT_DIR_OK; break;
561: default:
1.14 frystyk 562: ErrMsg("HTDaemon: bad -d option", argv[arg]);
1.13 frystyk 563: return_status = -4;
564: goto endproc;
1.2 timbl 565: }
566: } /* loop over characters */
567: #endif
1.3 timbl 568: /* Reference list heading */
1.14 frystyk 569: } else if (!strcmp(argv[arg], "-refhead")) {
570: if (arg+1 < argc && *argv[arg+1] != '-')
571: refhead = argv[++arg];
1.12 frystyk 572:
1.1 timbl 573: /* Print version and exit */
1.14 frystyk 574: } else if (!strcmp(argv[arg], "-version")) {
1.1 timbl 575: printf("WWW LineMode Browser version %s (WWW Library %s)\n",
576: VL, HTLibraryVersion);
1.14 frystyk 577: goto endproc;
578:
579: /* Source please */
580: } else if (!strcmp(argv[arg], "-source")) {
581: request->output_format = WWW_SOURCE;
582: HTOutputSource = YES; /* Turn on shortcut */
583: interactive = NO; /* JFG */
584:
1.1 timbl 585: #ifdef THINK_C
586: /* Echo to file */
1.14 frystyk 587: } else if (!strcmp(argv[arg], "-e")){
1.1 timbl 588: struct tm *tm_now; time_t time_now;
589: cecho2file("ThinkCconsole",FALSE,stdout);
590: time_now=time(NULL);tm_now=localtime(&time_now);
591: printf("\n--------------------------------------------"
592: "\n Time: %d.%.2d.%.2d %d:%d:%d\n"
593: "--------------------------------------------\n",
594: (*tm_now).tm_year,
595: (*tm_now).tm_mon+1,
596: (*tm_now).tm_mday,
597: (*tm_now).tm_hour,
598: (*tm_now).tm_min,
599: (*tm_now).tm_sec);
600:
601: /* debug socket library */
1.14 frystyk 602: } else if (!strcmp(argv[arg], "-s")) {
603: socketdebug=1;
1.1 timbl 604: #endif
605: /* endif long list of argument options */
606:
1.14 frystyk 607: } else {
608: ErrMsg("Bad Command Line Argument", argv[arg]);
609: }
1.1 timbl 610: } else { /* it doesn't start with a dash */
611:
612: /* Check for main argument
613: ** -----------------------
614: */
615: if (!argument_found) {
616: char * ref = HTParse(argv[arg], default_default, PARSE_ALL);
617: home_anchor = (HTParentAnchor*)HTAnchor_findAddress(ref);
618: free(ref);
619: argument_found = YES;
620:
621:
622: /* Check for successive keyword arguments
623: ** -------------------------------------
624: */
625: } else { /* Argument already found */
626: /* Collect keywords */
627: if (first_keyword){
628: first_keyword = NO;
629: } else {
630: strcat(keywords, " ");
631: }
632: strcat(keywords,HTStrip(argv[arg]));
633:
634: } /* argument already found */
635: } /* Not an option '-'*/
636: } /* End of argument loop */
637:
1.3 timbl 638: if (HTClientHost) HTSecure = YES;
639:
1.1 timbl 640: if (HTScreenHeight == -1) /* Default page size */
641: HTScreenHeight = interactive ? SCREEN_HEIGHT : 999999;
642:
1.4 timbl 643: #ifndef NO_RULES
644: {
645: char * rules = getenv("WWW_CONFIG");
1.14 frystyk 646: if (rules && HTLoadRules(rules) < 0) {
647: ErrMsg("Cant't open rule file", rules);
648: }
1.4 timbl 649: }
650: #endif
1.3 timbl 651:
1.18 frystyk 652: /* Force predefined presentations etc to be set up. Now it is taking
653: care of non-interactive, where no HTSaveLocally() of call backs are used */
654: if (interactive)
655: HTFormatInit(request->conversions);
656: else
657: HTFormatInitNIM(request->conversions);
1.3 timbl 658:
1.1 timbl 659: /* Open output file
660: ** ----------------
661: */
662: if (!interactive) { /* check for file name @@@@@ */
663: if (output_file_name) {
664: FILE * fp = fopen(output_file_name, "w");
665: if (!fp) {
1.14 frystyk 666: ErrMsg("Can't open file for writing", output_file_name);
667: return_status = -3;
1.13 frystyk 668: goto endproc;
1.1 timbl 669: }
1.4 timbl 670: output = fp;
1.1 timbl 671: }
1.18 frystyk 672: request->output_stream = HTFWriter_new(output,
673: output == stdout ? YES : NO);
1.11 frystyk 674: /* Just pump to stdout but YES: leave it open */
1.1 timbl 675: }
676:
677:
1.14 frystyk 678: /* Open Log File. Logfile via Telnet is now optional (HENRIK 11/02-94)
1.1 timbl 679: ** --------------------------
680: */
1.12 frystyk 681:
682: /* OLD VERSION
683: if (!logfile_root && HTClientHost)
684: {
1.1 timbl 685: logfile_root = DEFAULT_LOGFILE;
686: }
1.12 frystyk 687: */
688: if (logfile_flag) {
689: if(!logfile_root)
1.14 frystyk 690: logfile_root = HTClientHost ?
691: DEFAULT_LOGFILE : DEFAULT_LOCAL_LOGFILE;
692: log_file_name = (char*) malloc(strlen(logfile_root)+20);
1.12 frystyk 693:
1.1 timbl 694: #ifdef NO_GETPID
695: sprintf(log_file_name, "%s", logfile_root); /* No getpid() */
696: #else
697: sprintf(log_file_name, "%s-%d", logfile_root, getpid());
698: #endif
699: logfile = fopen(log_file_name, "a");
700: if (!logfile)
1.14 frystyk 701: ErrMsg("Can't open log file", log_file_name);
1.1 timbl 702: };
703:
704: /* Enable local directory access
705: */
706: HTDirReadme = HT_DIR_README_TOP; /* Readme presentation */
707: HTDirAccess = HTClientHost ? HT_DIR_SELECTIVE : HT_DIR_OK; /* browsing */
708:
709:
710: /* Make home page address
711: ** ----------------------
712: */
713: if (!home_anchor)
714: home_anchor = HTHomeAnchor ();
715:
716:
717: /* Non-interactive use
718: ** -------------------
719: */
1.14 frystyk 720: if (filter) { /* Just convert formats */
1.12 frystyk 721: HTBindAnchor((HTAnchor*)home_anchor, request);
1.18 frystyk 722: HTParseSocket(input_format, 0, request); /* From std UNIX input */
1.13 frystyk 723: goto endproc;
1.1 timbl 724: }
725:
726: /* Load first document
727: ** -------------------
728: */
1.9 timbl 729: if ( *keywords ? HTSearch(keywords, home_anchor, request)
1.14 frystyk 730: : HTLoadAnchor((HTAnchor*) home_anchor, request)) {
1.11 frystyk 731: HTHistory_record((HTAnchor *)home_anchor);
1.1 timbl 732:
733: } else { /* Can't even get last resort: give up */
734:
1.13 frystyk 735: char *addr = HTAnchor_address((HTAnchor *)home_anchor);
736:
1.14 frystyk 737: ErrMsg("Can't access document", addr);
1.13 frystyk 738: free(addr);
739: if (!HTMainText) {
740: return_status = -2; /* Can't get first page */
741: goto endproc;
742: }
1.1 timbl 743: }
1.11 frystyk 744:
1.13 frystyk 745: if (!HTMainText)
746: goto endproc; /* Hypertext object was not created */
1.1 timbl 747:
1.12 frystyk 748:
1.1 timbl 749: /* Main "Event Loop"
750: ** ----------------
751: */
752:
753: if (interactive) {
1.23 frystyk 754: while (Selection_Prompt());
1.1 timbl 755:
756: } else if (!HTOutputSource) { /* Non-interactive but formatted */
1.6 timbl 757: #ifdef OLD_CODE
1.4 timbl 758: fprintf(output, "\f"); /* Form feed for new page */
1.1 timbl 759: while(HText_canScrollDown(HTMainText)) {
760: HText_scrollDown(HTMainText);
1.4 timbl 761: fprintf(output, "\f"); /* Form feed for new page */
1.1 timbl 762: }
1.6 timbl 763: #endif
1.1 timbl 764: if (listrefs_option) {
765: Reference_List(NO); /* List without titles */
766: }
767: }
1.13 frystyk 768:
769: endproc:
770: HTRequest_delete(request);
771: if(default_default)
772: free(default_default);
1.18 frystyk 773:
1.13 frystyk 774: if(!return_status) { /* Good! */
1.8 duns 775: #ifdef VMS
1.1 timbl 776: return 1;
777: #else
778: return 0; /* Good */
779: #endif
1.13 frystyk 780: }
781: return return_status; /* Bad! */
1.1 timbl 782: } /* main() */
783:
784:
785:
786: /* Error_Selection
787: ** ---------------
788: ** Produce an error message.
789: **
790: */
791:
792: #ifdef __STDC__
793: PRIVATE void Error_Selection(void)
794: #else
795: PRIVATE void Error_Selection()
796: #endif
797:
798: {
799: fprintf(stderr, "%s", "Bad command, for list of commands type help.\n");
800: return;
801: }
802:
803:
1.14 frystyk 804: /* Display Help screen Help_screen
1.1 timbl 805: ** -------------------
806: **
807: ** Produce a help screen, displaying the current document address and a list of
808: ** available commands *in this context*.
809: ** ?? Perhaps this should be a hypertext page, not included in the history list.
810: */
811:
812: PRIVATE void help_screen NOARGS {
813:
814: char * current_address = HTAnchor_address((HTAnchor*)HTMainAnchor);
815: CONST char * title = HTAnchor_title(HTMainAnchor);
816:
817: printf("\n\nWWW LineMode Browser version %s (WWWLib %s) COMMANDS AVAILABLE\n\n",
818: VL, HTLibraryVersion);
819: if (title) printf("You are reading\n \"%s\"\nwhose address is\n %s\n\n",
820: title, current_address);
821: else printf("You are reading a document whose address is\n '%s' \n\n",
822: current_address);
823:
824: if (HText_canScrollDown(HTMainText)) {
825: printf(
826: " <RETURN> Move down one page within the document.\n");
827: printf(
828: " BOttom Go to the last page of the document.\n");
829: };
830:
831: if (HText_canScrollUp(HTMainText)) {
832: printf(
833: " Top Return to the first page of the document.\n");
834: printf(
835: " Up Move up one page within the document\n");
836: };
837:
838: if (HText_sourceAnchors(HTMainText) != 0) {
1.18 frystyk 839: printf(" List List the references from this document.\n *");
1.1 timbl 840: printf(" <number> Select a referenced document by number (from 1 to %d).\n",
841: HText_sourceAnchors(HTMainText));
842: }
843:
844: if (HTAnchor_isIndex(HTMainAnchor)) {
845: printf(
846: " Find <words> Search this index for given words (separated by spaces).\n");
847: }
848:
849: if (HTHistory_canBacktrack()) {
850: printf(" Recall List visited documents.\n");
851: printf(" Recall <number> Return to a previously visited document\n");
852: printf(" as numbered in the recall list.\n");
853: printf(" HOme Return to the starting document.\n");
854: printf(" Back Move back to the last document.\n");
855: }
856:
857: if (HTHistory_canMoveBy(1))
858: printf(" Next Take next link from last document.\n");
859:
860: if (HTHistory_canMoveBy(-1))
861: printf(" Previous Take previous link from last document.\n");
862:
1.14 frystyk 863: printf(" REFresh Refresh screen with current document\n");
1.12 frystyk 864: printf(" Go <address> Go to document of given [relative] address\n");
1.1 timbl 865:
866: #ifdef GOT_SYSTEM
867: if (!HTClientHost) { /* NOT for telnet guest! */
868: printf(" PRInt Print text of this document. *\n");
1.12 frystyk 869: printf(" ! <command> Execute shell <command> without leaving.\n");
870: printf(" > <file> Save the text of this document in <file>. *\n");
1.14 frystyk 871: printf(" If <file> exists use '>!' to overwrite it.\n");
1.12 frystyk 872: printf(" >> <file> Append the text of this document to <file>. *\n");
873: printf(" | <command> Pipe this document to the shell <command>. *\n");
1.1 timbl 874: #ifdef unix
1.12 frystyk 875: printf(" CD <directory> Change local working directory.\n");
1.1 timbl 876: #endif
877: printf("* Prefix these commands with \"Source \" to use raw source.\n\n");
878: }
879: #endif
880:
881: #ifdef SLAVE_PRINTER
882: printf(
883: " Ps Print text of this document to Terminal's Slave printer.\n");
884: #endif
885:
886: printf(" Verbose Switch to %sverbose mode.\n", WWW_TraceFlag ? "non-" : "");
887:
888: printf(" Help Display this page.\n");
889: printf(" Manual Jump to the online manual for this program\n");
1.14 frystyk 890: printf(" Quit Leave the www program.\n");
1.1 timbl 891: printf("\n");
1.14 frystyk 892: free(current_address);
893: } /* End of help_screen */
1.1 timbl 894:
895:
896: /* Select_Reference
897: ** ----------------
898: **
1.14 frystyk 899: ** After a reference is selected by the user, opens document, links into the
900: ** history list and displays.
1.1 timbl 901: **
902: ** On Entry:
903: ** int reference_num Number corresponding to the hypertext reference
904: ** given in the text.
905: */
906:
907: BOOL Select_Reference ARGS1(int,reference_num) {
908:
909: HTAnchor * destination;
910: HTChildAnchor * source = HText_childNumber(HTMainText, reference_num);
911:
912: if (!source) return NO; /* No anchor */
913: destination = HTAnchor_followMainLink((HTAnchor*) source);
1.9 timbl 914: if (!HTLoadAnchor(destination, request)) return NO; /* No link */
1.1 timbl 915: HTHistory_leavingFrom((HTAnchor*) source);
916: HTHistory_record(destination);
917:
918: return YES;
919:
920: } /* Select_Reference*/
921:
922:
923: /* Reference_List
924: ** --------------
925: ** Print out a list of HyperText References accumulated within the text.
926: **
927: ** On entry
928: ** titles Set: if we want titles where available
929: ** Clear: we only get addresses.
930: */
931:
932: PRIVATE void Reference_List ARGS1(BOOL, titles)
933:
934: {
935: int n;
936:
937: if (HText_sourceAnchors(HTMainText) == 0) {
1.4 timbl 938: fprintf(output,
939: "\n\n There are no references from this document.\n\n");
1.1 timbl 940: } else {
1.11 frystyk 941:
1.12 frystyk 942: fprintf(output, "\n%s\n", refhead);
1.1 timbl 943: for (n=1; n<=HText_sourceAnchors(HTMainText); n++) {
944: HTAnchor * destination =
945: HTAnchor_followMainLink(
946: (HTAnchor *)HText_childNumber(HTMainText, n)
947: );
948: HTParentAnchor * parent = HTAnchor_parent(destination);
949: char * address = HTAnchor_address(destination);
950: CONST char * title = titles ? HTAnchor_title(parent) : 0 ;
951:
1.4 timbl 952: fprintf(output, reference_mark, n);
953: fprintf(output, "%s%s\n",
1.1 timbl 954: ((HTAnchor*)parent!=destination) && title ? "in " : "",
955: (char *)(title ? title : address));
956: free(address);
957: }
958:
1.4 timbl 959: fprintf(output, "\n");
1.1 timbl 960: }
961: }
962:
963:
964: /* History_List
965: ** ------------
966: */
967: /* Display a history list of nodes visited during the session.
968: ** ?? This should really be a hypertext page (not itself in history!).
969: ** ?? Should have option to display address even when anchor has a title.
970: */
971:
972: PRIVATE void History_List NOARGS {
973:
974: int history_number = 1;
975: printf("\n Documents you have visited:-\n\n");
976:
977: do {
978:
979: char * address;
980: CONST char * title;
981: HTAnchor * anchor = HTHistory_read(history_number);
982: HTParentAnchor * parent;
983:
984: if (!anchor) break;
985: parent = HTAnchor_parent(anchor);
986: title = HTAnchor_title(parent);
987: address = HTAnchor_address(anchor);
988: #ifdef VIOLA
989: printf("\017R %2d\016) %s%s\n", /* SI user field SO */
990: #else
991: printf("R %2d) %s%s\n",
992: #endif
993: history_number,
994: ((HTAnchor*)parent!=anchor) && title ? "in " : "",
995: title ? title : address);
996: free(address);
997:
998: history_number++;
999:
1000: } while (YES);
1001:
1002: printf("\n");
1003: }
1004:
1005:
1006: /*
1007: ** Check_User_Input
1008: ** ----------------
1009: **
1010: ** Accepts shortened versions of commands.
1011: **
1012: ** On Entry:
1013: ** char *s Correct and full version of command, to which the user's
1014: ** input is compared.
1015: **
1016: ** On Exit:
1017: ** returns YES User's input corresponds to the command.
1018: ** NO Not a recognized command.
1019: */
1020:
1021: #define Check_User_Input(command) \
1022: (!strncasecomp (command, this_word, strlen(this_word)))
1023:
1024:
1025: /* USER INTERFACE
1026: ** ==============
1027: */
1028:
1029: /* Selection_Prompt
1030: ** ----------------
1031: ** Produces a prompt at the bottom of a page full of text. The prompt varies
1032: ** depending on the options avaliable.
1033: */
1034:
1035: #ifdef __STDC__
1.23 frystyk 1036: PRIVATE BOOL Selection_Prompt(void)
1.1 timbl 1037: #else
1.23 frystyk 1038: PRIVATE BOOL Selection_Prompt()
1.1 timbl 1039: #endif
1040: {
1.14 frystyk 1041: int length_of_prompt = 0;
1042: BOOL is_index = HTAnchor_isIndex(HTMainAnchor);
1043:
1044: if (!HText_canScrollDown(HTMainText) &&
1045: !HTAnchor_hasChildren(HTMainAnchor) && !is_index &&
1046: (!HTHistory_canBacktrack())) {
1047: ErrMsg("No way out of here, so I exit!", NULL);
1.23 frystyk 1048: return NO; /* Exit if no other options */
1.14 frystyk 1049: }
1050: HText_setStale(HTMainText); /* We corrupt the display */
1.1 timbl 1051:
1.14 frystyk 1052: #ifndef VM /* Normal prompt */
1053: if (is_index){
1054: printf("FIND <keywords>, ");
1055: length_of_prompt = length_of_prompt + 14;
1056: }
1057: if (HTAnchor_hasChildren(HTMainAnchor)!=0){
1058: int refs = HText_sourceAnchors(HTMainText);
1059: if (refs>1) {
1060: printf("1-%d, ", refs);
1061: length_of_prompt = length_of_prompt + 6; /* Roughly */
1062: }
1063: else {
1064: printf("1, ");
1065: length_of_prompt = length_of_prompt + 3;
1.1 timbl 1066: }
1.14 frystyk 1067: }
1068: if (HTHistory_canBacktrack()){
1069: printf(PROMPT_MARK, "Back"); printf(", ");
1.1 timbl 1070: #ifdef LONG_PROMPT
1.14 frystyk 1071: printf(PROMPT_MARK, "Recall"); printf(", ");
1.1 timbl 1072: #endif
1.14 frystyk 1073: length_of_prompt = length_of_prompt + 6;
1074: }
1075: if (HText_canScrollUp(HTMainText)){
1076: printf(PROMPT_MARK,"Up"); printf(", ");
1077: length_of_prompt = length_of_prompt + 4;
1078: }
1079: if (HText_canScrollDown(HTMainText)) {
1080: printf("<RETURN> for more, ");
1081: length_of_prompt = length_of_prompt + 19;
1082: }
1083: if (length_of_prompt <= 47) {
1084: printf(PROMPT_MARK, "Quit"); printf(", ");
1085: }
1086:
1087: printf("or Help: ");
1.1 timbl 1088:
1089: #else /* Special prompt for VM assuming PF keys set*/
1.14 frystyk 1090: if (is_index) {
1091: printf("FIND <words>, "); /* 14 */
1092: length_of_prompt = length_of_prompt + 14;
1093: }
1094: if (HTAnchor_hasChildren(HTMainAnchor)!=0){
1095: int refs = HText_sourceAnchors(HTMainText);
1096: if (refs>1) {
1097: printf("1-%d, ", refs);
1098: length_of_prompt = length_of_prompt + 6; /* approx 6 */
1099: }
1100: else {
1101: printf("1, ");
1102: length_of_prompt = length_of_prompt + 3;
1103: }
1104: }
1105: if (HTHistory_canMoveBy(1)) {
1106: printf("PF2=Next ");
1107: length_of_prompt = length_of_prompt + 9; /* 9 */
1108: }
1109: printf("PF3=Quit PF4=Return, ");
1110: length_of_prompt = length_of_prompt + 21; /* 21 */
1111:
1112: if (HTHistory_canBacktrack()){
1113: printf("Recall, ");
1114: length_of_prompt = length_of_prompt + 8; /* 8 */
1115: }
1116: if (HText_canScrollUp(HTMainText)){
1117: printf(PROMPT_MARK,"PF7=Up "); printf(", ");
1118: length_of_prompt = length_of_prompt + 7; /* 7 */
1119: }
1120: if (HText_canScrollDown(HTMainText)){
1121: printf("PF8=Down ");
1122: length_of_prompt = length_of_prompt + 9; /* 9 */
1123: }
1124: if (length_of_prompt<70) printf("PF11=Help"); /* 9 */
1125: /* EQUAL 82 */
1.1 timbl 1126: #endif
1127:
1128: /* Read in the user's input, and deal with it as necessary.
1129: **
1130: ** Any Command which works returns from the routine. If nothing
1131: ** works then a search or error message down at the bottom.
1132: */
1.14 frystyk 1133: {
1.1 timbl 1134: int reference_num;
1.14 frystyk 1135: char * the_choice = 0; /* preserved user command */
1136: char * this_word = 0; /* First word of command */
1137: char * this_command; /* this_word and following */
1138: char * next_word; /* Second word */
1139: char * other_words; /* Second word and following */
1.1 timbl 1140:
1141: #ifdef NEWLINE_PROMPT
1.14 frystyk 1142: printf("\n"); /* For use on VM to flush out the prompt */
1.1 timbl 1143: #endif
1.23 frystyk 1144: if (!fgets(choice, RESPONSE_LENGTH, stdin)) /* Read User Input */
1145: return NO; /* Exit if EOF */
1.21 luotonen 1146:
1.14 frystyk 1147: StrAllocCopy (the_choice, choice); /* Remember it as is, */
1148: if (the_choice[strlen(the_choice)-1] == '\n') /* The final \n */
1149: the_choice[strlen(the_choice)-1] = '\0';
1.1 timbl 1150:
1151: #ifdef VM /* Clear the screen (on screen-mode systems) */
1152: clear_screen();
1.14 frystyk 1153: #endif
1154: this_word = strtok (choice, " \t\n\r"); /* Tokenize user input */
1.1 timbl 1155: this_command = the_choice;
1156: if (this_word) {
1.14 frystyk 1157: next_word = strtok (NULL, " \t\n\r");
1158: other_words = the_choice + (next_word - choice);
1159: }
1.1 timbl 1160: else
1.14 frystyk 1161: goto down; /* Empty input : scroll down */
1.1 timbl 1162:
1163: /* Process Command
1164: ** ---------------
1165: */
1.14 frystyk 1166: /* Giant switch for incoming commands, many of which are single-letter. */
1167: loop: switch (TOUPPER(*this_word)) {
1.1 timbl 1168:
1.14 frystyk 1169: case '0':
1170: case '1':
1171: case '2':
1172: case '3':
1173: case '4':
1174: case '5':
1175: case '6':
1176: case '7':
1177: case '8':
1178: case '9':
1179: sscanf(this_word,"%d",&reference_num);
1180: if ((reference_num >= 1) &&
1181: (reference_num <= HText_sourceAnchors(HTMainText))) {
1182: Select_Reference(reference_num); /* Select a reference */
1183: goto ret;
1184: }
1185: break;
1.1 timbl 1186:
1.14 frystyk 1187: case 'B':
1188: if (Check_User_Input("BACK")) { /* Return to previous node */
1189: if (HTHistory_canBacktrack()) {
1190: HTLoadAnchor(HTHistory_backtrack(), request);
1191: } else {
1192: printf("\n The BACK command cannot be used,");
1193: printf(" as there are no previous documents\n");
1194: }
1195: }
1196: else if (Check_User_Input("BOTTOM")) { /* Scroll to bottom */
1197: HText_scrollBottom(HTMainText);
1198: }
1199: goto ret;
1200: break;
1.1 timbl 1201:
1202: #ifdef unix
1.14 frystyk 1203: case 'C':
1204: if (Check_User_Input("CD")) /* Change working directory ? */
1205: goto lcd;
1206: break;
1.1 timbl 1207: #endif
1208:
1.14 frystyk 1209: case 'D':
1210: if (Check_User_Input("DOWN")) { /* Scroll down one page */
1211: down: if (HText_canScrollDown(HTMainText))
1212: HText_scrollDown(HTMainText);
1213: goto ret;
1214: }
1215: break;
1.1 timbl 1216:
1.14 frystyk 1217: case 'E': /* Quit program ? Alternative command */
1218: if (Check_User_Input("EXIT"))
1.23 frystyk 1219: goto stop;
1.14 frystyk 1220: break;
1221:
1222: case 'F': /* Keyword search ? */
1223: if (is_index && Check_User_Input("FIND")) {
1224: find: if (next_word && HTSearch(other_words, HTMainAnchor, request))
1225: HTHistory_record((HTAnchor*)HTMainAnchor);
1226: goto ret;
1227: }
1228: break;
1.1 timbl 1229:
1.14 frystyk 1230: case 'G':
1231: if (Check_User_Input("GOTO")) { /* GOTO */
1.15 frystyk 1232: if (next_word &&
1233: HTLoadRelative(next_word, HTMainAnchor, request))
1.14 frystyk 1234: HTHistory_record((HTAnchor*) HTMainAnchor);
1.1 timbl 1235: goto ret;
1.14 frystyk 1236: }
1237: break;
1.1 timbl 1238:
1.14 frystyk 1239: case '?':
1.1 timbl 1240: help_screen();
1241: goto ret;
1242:
1.14 frystyk 1243: case 'H':
1244: if (Check_User_Input("HELP")){ /* help menu, ..*/
1245: help_screen(); /*!! or a keyword search ? */
1246: goto ret;
1247: }
1248: else if (Check_User_Input("HOME")) { /* back HOME */
1249: if (!HTHistory_canBacktrack()){
1250: HText_scrollTop(HTMainText);
1251: } else {
1252: HTLoadAnchor(HTHistory_recall(1), request);
1253: /*!! this assumes history is kept.*/
1254: }
1255: goto ret;
1256: } /* if HOME */
1257: break;
1.1 timbl 1258:
1.14 frystyk 1259: case 'K': /* Keyword search ? */
1260: if (is_index && Check_User_Input("KEYWORDS")) {
1261: goto find;
1262: }
1263: break;
1.1 timbl 1264:
1.14 frystyk 1265: case 'L':
1266: if (Check_User_Input("LIST")){ /* List of references ? */
1.18 frystyk 1267: Reference_List(!OutSource);
1.14 frystyk 1268: goto ret;
1269: }
1270: #ifdef unix
1271: else if (Check_User_Input ("LCD")) { /* Local change dir ? */
1.16 frystyk 1272: extern int chdir();
1.14 frystyk 1273: lcd: if (!next_word) { /* Missing argument */
1274: printf ("\nPlease specify the name of the new local directory.\n");
1275: goto ret;
1276: }
1277: if (chdir (next_word)) { /* failed : say why */
1278: fprintf (stderr, "\n ");
1279: perror (next_word);
1.1 timbl 1280: }
1.14 frystyk 1281: else { /* Success : display new local directory */
1282: /* AS Sep 93 */
1283: #ifdef NO_GETWD /* No getwd() on this machine */
1284: #ifdef HAS_GETCWD /* System V variant SIGN CHANGED TBL 921006 !! */
1285: printf ("\nLocal directory is now:\n %s\n",
1286: getcwd (choice, sizeof(choice)));
1.5 secret 1287: #else /* has NO getcwd */
1.16 frystyk 1288: ErrMsg("This platform does not support getwd() or getcwd()", NULL);
1.5 secret 1289: #endif /* has no getcwd */
1290: #else /* has getwd */
1.16 frystyk 1291: printf("\nLocal directory is now:\n %s\n", getwd (choice));
1.5 secret 1292: #endif /* has getwd */
1.14 frystyk 1293: /* End AS Sep 93 */
1294: }
1295: goto ret;
1296: }
1.1 timbl 1297: #endif
1.14 frystyk 1298: break;
1.1 timbl 1299:
1.14 frystyk 1300: case 'M':
1301: if (Check_User_Input("MANUAL")){ /* Read User manual */
1.10 frystyk 1302: if (HTLoadRelative(MANUAL, HTMainAnchor, request))
1.14 frystyk 1303: HTHistory_record((HTAnchor*)HTMainAnchor);
1.1 timbl 1304: goto ret;
1.14 frystyk 1305: }
1306: break;
1307:
1308: case 'N':
1309: if (Check_User_Input("NEXT")) {
1310: if (!HTHistory_canMoveBy(1)) { /* No nodes to jump back to */
1311: printf("\n Can't take the NEXT link from the last");
1312: if (!HTHistory_canBacktrack())
1313: printf(" document as there is no last");
1314: printf(" document.\n");
1315: goto ret;
1.1 timbl 1316: }
1.9 timbl 1317: HTLoadAnchor(HTHistory_moveBy(1), request);
1.1 timbl 1318: goto ret;
1319: }
1320: break;
1321:
1.14 frystyk 1322: case 'P':
1323: if (Check_User_Input("PREVIOUS")) {
1324: if (!HTHistory_canMoveBy(-1)){
1325: printf("\n Can't take the PREVIOUS link from the last");
1326: if (!HTHistory_canBacktrack())
1327: printf(" document as there is no last");
1328: printf(" document.\n");
1329: goto ret;
1330: }
1331: HTLoadAnchor(HTHistory_moveBy(-1), request);
1332: goto ret;
1333: }
1.1 timbl 1334: #ifdef GOT_SYSTEM
1.14 frystyk 1335: else if (!HTClientHost && Check_User_Input("PRINT")) {
1336: char * address = HTAnchor_address((HTAnchor*)HTMainAnchor);
1337: char * command;
1338: char * template = (char*)getenv("WWW_PRINT_COMMAND");
1339: int result;
1.1 timbl 1340:
1.14 frystyk 1341: if (!template) template = "www -n -na -p66 '%s' | lpr";
1342: command = (char *) malloc(strlen(address)+strlen(template)+20);
1343: sprintf(command, template, address);
1344: result = system(command);
1345: free(address);
1346: free(command);
1347: if (result) printf(" %s\n returns %d\n", command, result);
1348: goto ret;
1349: }
1.1 timbl 1350: #endif
1.14 frystyk 1351: /* this command prints the entire current text to the
1352: terminal's printer; at the end it displays the top of the text */
1.1 timbl 1353: #ifdef SLAVE_PRINTER
1354: #define SLAVE_PRINTER_ON "\033\133\065\151"
1355: #define SLAVE_PRINTER_OFF "\033\133\064\151"
1.14 frystyk 1356:
1357: if (Check_User_Input("PS")) {
1358: printf ("%s",SLAVE_PRINTER_ON);
1359: printf("\f"); /* Form feed for new page */
1360: HText_scrollTop(HTMainText);
1361: while(HText_canScrollDown(HTMainText)) {
1362: HText_scrollDown(HTMainText);
1363: }
1364: printf("\f"); /* Form feed for new page */
1365: printf ("%s",SLAVE_PRINTER_OFF);
1366: HText_scrollTop(HTMainText);
1.23 frystyk 1367: goto ret;
1.14 frystyk 1368: }
1.1 timbl 1369: #endif
1.14 frystyk 1370: break;
1.1 timbl 1371:
1.14 frystyk 1372: case 'Q': /* Quit program ? */
1373: if (Check_User_Input("QUIT")) {
1.1 timbl 1374: #ifdef VM
1.14 frystyk 1375: if (HTHistory_canBacktrack()){ /* Means one level only */
1376: HTLoadAnchor(HTHistory_backtrack(), request);
1377: goto ret;
1378: } else {
1.23 frystyk 1379: goto stop; /* On last level, exit */
1.14 frystyk 1380: }
1.1 timbl 1381: #endif
1.23 frystyk 1382:
1.1 timbl 1383: /* JFG 9/7/92, following a complaint of 'q' mis-typed for '1'.
1384: JFG Then made optional because I hate it !!!
1385: TBL made it only affect remote logged on users. 921122 */
1386:
1.14 frystyk 1387: if (HTClientHost && (strcasecomp(this_word, "quit") != 0) ) {
1388: printf ("\n Please type \"quit\" in full to leave www.\n");
1389: goto ret;
1.1 timbl 1390: }
1.23 frystyk 1391: goto stop;
1.14 frystyk 1392: }
1393: break;
1.1 timbl 1394:
1.14 frystyk 1395: case 'R':
1.1 timbl 1396: #ifdef VM
1.14 frystyk 1397: if (Check_User_Input("RETURN")) /* Means quit program */
1.23 frystyk 1398: goto stop;
1.1 timbl 1399: #endif
1.14 frystyk 1400: if (Check_User_Input("RECALL")) {
1.1 timbl 1401: int recall_node_num;
1.14 frystyk 1402:
1403: if (!HTHistory_canBacktrack()) { /* No nodes to recall */
1404: printf("\n No other documents to recall.\n");
1405: goto ret;
1.1 timbl 1406: }
1407:
1.14 frystyk 1408: /* Previous node number exists, or does the user just */
1409: /* require a list of nodes visited? */
1.1 timbl 1410: if (next_word) {
1.14 frystyk 1411: if ((recall_node_num = atoi(next_word)) > 0) /* Parm OK */
1.9 timbl 1412: HTLoadAnchor(HTHistory_recall(recall_node_num),
1.14 frystyk 1413: request);
1.1 timbl 1414: else
1415: Error_Selection();
1416: }
1417: else
1.14 frystyk 1418: History_List();
1.1 timbl 1419: goto ret;
1420: } else if (Check_User_Input("REFRESH")){
1.14 frystyk 1421: HText_select(HTMainText); /* Refresh screen */
1.1 timbl 1422: goto ret;
1423: }
1424: break;
1425:
1.14 frystyk 1426: case 'S': /* TBL 921009 */
1427: if (Check_User_Input("SOURCE")) { /* Apply to source */
1428: if (!next_word) goto ret; /* Should refresh as source @@@ */
1.18 frystyk 1429: OutSource = YES; /* Load and print as source */
1.14 frystyk 1430: this_word = next_word; /* Move up one word */
1431: next_word = strtok (NULL, " \t\n\r");
1432: this_command = the_choice + (this_word - choice);
1433: other_words = the_choice + (next_word - choice);
1434: goto loop; /* Go treat as before */
1435: } else if (Check_User_Input("SET")) { /* config */
1436: HTSetConfiguration(other_words);
1437: goto ret;
1438: }
1439: break;
1.4 timbl 1440:
1.14 frystyk 1441: case 'T':
1442: if (Check_User_Input("TOP")) { /* Return to top */
1443: HText_scrollTop(HTMainText);
1444: goto ret;
1445: }
1446: break;
1447:
1448: case 'U':
1449: if (Check_User_Input("UP")) { /* Scroll up one page */
1450: HText_scrollUp(HTMainText);
1451: goto ret;
1452: }
1453: break;
1.1 timbl 1454:
1.14 frystyk 1455: case 'V':
1456: if (Check_User_Input("VERBOSE")) { /* Switch verbose mode */
1457: WWW_TraceFlag = ! WWW_TraceFlag;
1458: printf ("\n Verbose mode %s.\n", WWW_TraceFlag ? "ON":"OFF");
1459: goto ret;
1460: }
1461: break;
1.1 timbl 1462:
1.14 frystyk 1463: case '>':
1464: if (!HTClientHost) {
1.18 frystyk 1465: SaveOutputStream(this_word, next_word);
1466: goto ret;
1467: }
1468: break;
1.14 frystyk 1469:
1.20 frystyk 1470: #ifdef GOT_PIPE
1.14 frystyk 1471: case '|':
1472: if (!HTClientHost) { /* Local only!!!! */
1473: char * address = HTAnchor_address((HTAnchor*) HTMainAnchor);
1474: char * command;
1475: int result;
1.1 timbl 1476:
1.14 frystyk 1477: command = (char*) malloc(strlen(address)
1478: +strlen(this_command)+30);
1479:
1480: #ifdef VM
1481: sprintf(command, "PIPE CMS WWW %s \"%s\" | %s",
1482: /* Note format is | > */
1483: #else
1484: sprintf(command, "www %s \"%s\" %s",
1485: #endif
1.18 frystyk 1486: OutSource ? "-source" : "-n -na -p", address, this_command);
1.14 frystyk 1487:
1488: printf("Command: %s\n", command);
1489: result = system(command);
1490: if (result)
1491: printf(" %s returns %d\n", command, result);
1492: free(command);
1493: free(address);
1494: goto ret;
1495: }
1.1 timbl 1496: #endif
1497:
1498: #ifdef GOT_SYSTEM
1.14 frystyk 1499: case '!':
1500: if (!HTClientHost) { /* Local only!!!!!!! */
1.1 timbl 1501: int result;
1.28 ! frystyk 1502: ErrMsg("Executing", this_command);
1.1 timbl 1503: result = system(strchr(this_command, '!') + 1);
1504: if (result) printf(" %s returns %d\n",
1.14 frystyk 1505: strchr(this_command, '!') + 1, result);
1.1 timbl 1506: goto ret;
1.14 frystyk 1507: }
1.1 timbl 1508: #endif
1.14 frystyk 1509: default:
1510: break;
1511: } /* Switch on 1st character */
1.1 timbl 1512:
1.14 frystyk 1513: if (is_index && *this_word) { /* No commands, search keywords */
1.16 frystyk 1514: next_word = other_words = this_command;
1515: goto find;
1.1 timbl 1516: } else {
1517: Error_Selection();
1518: }
1519:
1520: ret: free (the_choice);
1.23 frystyk 1521: return YES;
1522:
1523: stop: free(the_choice);
1524: return NO;
1.1 timbl 1525: } /* Get user selection */
1.14 frystyk 1526: } /* Selection_Prompt */
1527:
1.1 timbl 1528:
1.18 frystyk 1529: /* -------------------------------------------------------------------------
1.19 frystyk 1530: General Error Message for Line Mode Browser. If verbose mode is on, then
1531: the message is passed to stderr.
1.14 frystyk 1532:
1.18 frystyk 1533: Henrik Frystyk 02/03-94
1534: ------------------------------------------------------------------------- */
1.14 frystyk 1535: PRIVATE void ErrMsg ARGS2(char *, Msg, char *, Str)
1536: {
1.18 frystyk 1537: if (WWW_TraceFlag) {
1538: if (Str)
1.28 ! frystyk 1539: fprintf(stderr, "Line Mode Browser: %s (%s)\n", Msg, Str);
1.18 frystyk 1540: else
1.28 ! frystyk 1541: fprintf(stderr, "Line Mode Browser: %s\n", Msg);
1.18 frystyk 1542: }
1543: }
1544:
1545:
1546: /* -------------------------------------------------------------------------
1547: This function puts up a stream to a file in order to save a document. This
1548: is activated by '>', '>>' or '>!' from the prompt line.
1549: Returns NO if Error and YES if OK
1550:
1551: Henrik Frystyk 02/03-94
1552: ------------------------------------------------------------------------- */
1553: PRIVATE BOOL SaveOutputStream ARGS2(char *, This, char *, Next)
1554: {
1555: FILE *fp;
1556: char *fname;
1557: char *fmode;
1558:
1559: /* Checks if file exists. Can be overruled by using '>!' */
1560: if (*(This+1) == '>') { /* Append to file */
1561: fmode = "a";
1562: fname = *(This+2) ? (This+2) : Next;
1563: } else if (*(This+1) == '!') {
1564: fmode = "w"; /* Overwrite file */
1565: fname = *(This+2) ? (This+2) : Next;
1566: } else { /* File name follows */
1567: fmode = "w";
1568: fname = *(This+1) ? (This+1) : Next;
1569: if (fname) { /* See if file exists */
1570: if ((fp = fopen(fname, "r")) != NULL) {
1571: printf("%s: File exists\n", fname);
1572: fclose(fp);
1573: return NO;
1574: }
1575: }
1576: }
1577: if (!fname) /* No file name given */
1578: return NO;
1579: if ((fp = fopen(fname, fmode)) == NULL) {
1580: ErrMsg("Can't access file", fname);
1581: return NO;
1582: }
1583:
1584: /* Now, file is open and OK: reload the text and put up a stream for it! */
1.20 frystyk 1585: ErrMsg("Save file", fname);
1.18 frystyk 1586: {
1587: BOOL ret = NO;
1588: HTRequest *req = HTRequest_new(); /* Set up a new request */
1589: HTFormatInitNIM(req->conversions); /* Non-interactive mode */
1590: if(OutSource)
1591: req->output_format = WWW_SOURCE;
1592: req->output_stream = HTFWriter_new(fp, NO);
1593: HTForceReload = YES;
1594: ret = HTLoadAnchor((HTAnchor*) HTMainAnchor, req);
1595: HTForceReload = NO;
1596: HTRequest_delete(req);
1597: return ret;
1598: }
1.14 frystyk 1599: }
1.1 timbl 1600:
1.18 frystyk 1601: /* End HTBrowse.c */
1.14 frystyk 1602:
Webmaster