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