Annotation of libwww/LineMode/src/HTBrowse.c, revision 1.170

1.44      frystyk     1: /*                                                                  HTBrowse.c
                      2: **     HYPERTEXT BROWSER FOR DUMB TERMINALS
                      3: **
1.62      frystyk     4: **     (c) COPRIGHT MIT 1995.
1.44      frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
1.170   ! frystyk     6: **     @(#) $Id: HTBrowse.c,v 1.169 1996/12/05 23:20:23 eric Exp $
1.1       timbl       7: **
                      8: **  Authors:
                      9: **     NP:  Nicola Pellow  Tech.Student CERN 1990-91
1.61      frystyk    10: **     TBL: Tim Berners-Lee CERN (timbl@w3.org)
                     11: **     JFG: Jean-Francois Groff, Cooperant CERN 1991-92 (jfg@dxcern.cern.ch)
1.1       timbl      12: **     DR:  Dudu Rashty +972-2-584848 <RASHTY@hujivms.bitnet>
1.8       duns       13: **     MD:  Mark Donszelmann, DELPHI CERN, (duns@vxdeop.cern.ch)
1.96      frystyk    14: **     HFN: Henrik Frystyk Nielsen, MIT, (frystyk@w3.org)
1.1       timbl      15: **
                     16: **  History:
                     17: **
                     18: **   4 Dec 90:  Written from scratch (NP)
                     19: **  11 Feb 91:  Code written by TBL so that the browser could be linked with
                     20: **              code produced by Bernd Pollermann, enabling access to the
                     21: **              data on CERNVM. This involved changing the code to handle file
                     22: **              numbers rather than file pointers.
                     23: **  18 Mar 91:  The feature of history mechanism was included, enabling a  
                     24: **              record of previous nodes visited to be kept.
                     25: **   6 Apr 91:  When a node is accessed, it is immediately read into a 
1.40      frystyk    26: **              buffer, in an unformatted state, as soon as the connection is  
1.160     frystyk    27: **              made, so that the server is freed as quickly as possible. 
1.1       timbl      28: **              The program now also uses the additional modules HTBufferFile.c
                     29: **              and HTBufferFile.h.
                     30: **  17 Apr 91:  Can be used on machines running ANSI C and ordinary C.
                     31: **  10 May 91:  Formatted text is stored in a linked list buffer which allows
                     32: **              scrolling and better page breaks in the middle of text.
                     33: **              Code incorporated by Tim BL, to enable anonymous FTP.          
                     34: **  21 May 91:  Accepts various parameters on the command line.
                     35: **  19 Aug 91:  Currently available in Unix, VAX/VMS and MVS environments.
                     36: **  21 Nov 91:  Character grid uses new architecture. (TBL)
                     37: **              added -w option, new commands, print,
                     38: **                  ...        See Features.html for further details
                     39: **  16 Jan 92:  Put in VIOLA-compatible options - see \017 characters.
                     40: **                  \017 and \016 bracket user-selectable input.
                     41: **  27 Feb 92: New handling of user input, enhanced command syntax. (JFG)
                     42: **  18 May 92: PS command see ifdef SLAVE_PRINTER (DR/TBL)
                     43: **   6 Oct 92:  Painful recovery from someone(?)'s attept to pretty print.(TBL)
                     44: **             Please see coding style guide before changing indentation etc!
                     45: **     Mar 93: Force on HTFile's HTDirAccess and HTDirReadme flags.
1.8       duns       46: **   3 Nov 93: (MD) Changed vms into VMS
1.99      frystyk    47: **             (MD) Assigne OUTPUT in main, not at initialize (VMS only)
1.1       timbl      48: **
                     49: ** Compilation-time macro options
                     50: **
                     51: **     REF_MARK        Printf string to be used for printing anchor numbers
                     52: **     END_MARK        String to be used to denote the end of a document
                     53: */
                     54: 
1.96      frystyk    55: #include "WWWLib.h"
                     56: #include "WWWMIME.h"
1.110     frystyk    57: #include "WWWCache.h"
1.96      frystyk    58: #include "WWWApp.h"
1.138     frystyk    59: #include "WWWTrans.h"
1.111     frystyk    60: #include "WWWInit.h"
1.92      frystyk    61: 
1.96      frystyk    62: #include "GridText.h"                               /* Hypertext definition */
1.68      frystyk    63: #include "HTBrowse.h"                       /* Things exported, short names */
1.138     frystyk    64: 
1.121     eric       65: #include "CSLApp.h" /* the PICApp library should provide everything the app needs */
1.126     hallam     66: #include "CSLL.h"
1.121     eric       67: #include "CSUser.h"
1.124     eric       68: #include "CSUsrLst.h"
1.40      frystyk    69: 
1.120     frystyk    70: #ifndef W3C_VERSION
                     71: #define W3C_VERSION            "Unspecified"
1.40      frystyk    72: #endif
                     73: 
1.96      frystyk    74: #define APP_NAME               "W3CLineMode"
1.120     frystyk    75: #define APP_VERSION            W3C_VERSION
1.86      frystyk    76: 
1.68      frystyk    77: /* Default page for "Manual" command */
1.140     frystyk    78: #define MANUAL "http://www.w3.org/pub/WWW/LineMode/User/QuickGuide.html"
1.40      frystyk    79: 
1.68      frystyk    80: /* Default page for "help" command */
1.140     frystyk    81: #define C_HELP "http://www.w3.org/pub/WWW/LineMode/User/Commands.html"
1.1       timbl      82: 
1.68      frystyk    83: /* Default page for "-help" command line option */
1.140     frystyk    84: #define L_HELP "http://www.w3.org/pub/WWW/LineMode/User/CommandLine.html"
1.37      howcome    85: 
1.68      frystyk    86: #define DEFAULT_OUTPUT_FILE    "www.out"
                     87: #define DEFAULT_RULE_FILE      "www.conf"
                     88: #define DEFAULT_LOG_FILE               "www.log"
1.170   ! frystyk    89: #define DEFAULT_MEMLOG         "www.mem"
1.126     hallam     90: #define DEFAULT_USERLIST_FILE  "PICSusrs.html"
1.68      frystyk    91: 
1.170   ! frystyk    92: #if 0
        !            93: #define HT_MEMLOG
        !            94: #endif
        !            95: 
1.68      frystyk    96: #define PROMPT                 "%s"
                     97: #define REF_MARK               "[%d]"
                     98: #define END_MARK               "[END]"
1.1       timbl      99: 
1.72      frystyk   100: #define SCREEN_WIDTH           79            /* Default width of the screen */
1.13      frystyk   101: #define MIN_SCREEN_WIDTH       10 
                    102: #define MAX_SCREEN_WIDTH       150      
1.72      frystyk   103: #define SCREEN_HEIGHT          24                /* Default number of lines */
1.13      frystyk   104: #define MIN_SCREEN_HEIGHT      5 
1.14      frystyk   105: #define MAX_SCREEN_HEIGHT      200      
1.72      frystyk   106: 
                    107: #define MAX_HISTORY            20      /* Don't list more than this in list */
1.1       timbl     108: 
1.68      frystyk   109: #define RESPONSE_LENGTH                1024     /* Maximum length of users response */
1.16      frystyk   110: 
1.94      frystyk   111: #define SHOW_MSG               (WWWTRACE || HTAlert_interactive())
1.68      frystyk   112: #define CHECK_INPUT(a, b)      (!strncasecomp ((a), (b), strlen((b))))
1.50      frystyk   113: 
1.167     frystyk   114: #define DEFAULT_I_TIMEOUT      1000       /* Interactive timeout in millies */
                    115: #define DEFAULT_NI_TIMEOUT     10000  /* Non-interactive timeout in millies */
1.96      frystyk   116: 
                    117: #define DEFAULT_FORMAT         WWW_PRESENT
1.81      frystyk   118: 
1.50      frystyk   119: #if defined(__svr4__)
                    120: #define CATCH_SIG
                    121: #endif
1.40      frystyk   122: 
                    123: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org (Anton Tropashko) */
                    124: #ifdef CYRILLIC
1.68      frystyk   125: #include "a_stdio.h"
1.40      frystyk   126: struct ARc arc;
                    127: #endif
1.2       timbl     128: 
1.68      frystyk   129: /* Screen size parameters */
1.40      frystyk   130: PUBLIC int             HTScreenWidth   = SCREEN_WIDTH;        /* By default */
                    131: PUBLIC int             HTScreenHeight  = -1;              /* -1 = Undefined */
1.68      frystyk   132: 
                    133: /* Anchor specific information */
1.40      frystyk   134: PUBLIC BOOL            display_anchors = YES;      /* Show anchors in text? */
                    135: PUBLIC char *          start_reference = NULL;   /* Format for start anchor */
                    136: PUBLIC char *          end_reference = REF_MARK;          /* for end anchor */
                    137: PUBLIC char *          reference_mark = "[%d] ";     /* for reference lists */
                    138: PUBLIC char *          end_mark = END_MARK;      /* Format string for [End] */
1.8       duns      139: 
1.96      frystyk   140: typedef enum _LMFlags {
                    141:     LM_FILTER  = 0x1,
                    142:     LM_REFS    = 0x2,
                    143:     LM_REFORMAT = 0x4,
                    144:     LM_PREEMTIVE= 0x8
                    145: } LMFlags;
                    146: 
1.118     eric      147: struct _LineMode {
1.115     frystyk   148:     HTRequest *                console;                           /* For user input */
1.96      frystyk   149:     HTParentAnchor *   anchor;
                    150:     HTList *           active;                   /* List of acitve contexts */
                    151:     HTList *           presenters;
                    152:     HTHistory *                history;                             /* History list */
                    153:     char *             cwd;                              /* Current dir URL */
                    154:     char *             rules;
                    155:     char *             logfile;
                    156:     char *             outputfile;
                    157:     char *             host;
                    158:     int                        trace;
1.167     frystyk   159:     int                        timer;
1.96      frystyk   160:     HTFormat           format;                 /* Input format from console */
                    161:     LMFlags            flags;
1.118     eric      162:     HTView *           pView;
1.126     hallam    163:     char *             userList;
1.124     eric      164:     CSUser_t *                 pCSUser;
1.132     eric      165:     BOOL               noPICSPasswords;
1.118     eric      166: };
1.96      frystyk   167: 
                    168: typedef enum _LMState {
                    169:     LM_UPDATE  = 0x1,
                    170:     LM_NO_UPDATE= 0x2,
                    171:     LM_DONE    = 0x4,
1.146     frystyk   172:     LM_INACTIVE        = 0x8,
                    173:     LM_IGNORE  = 0x10
1.96      frystyk   174: } LMState;
                    175: 
                    176: typedef struct _Context {
                    177:     LMState            state;
                    178:     HTRequest *                request;
                    179:     LineMode *         lm;
1.108     frystyk   180:     HTParentAnchor *   source;    /* The source if we are using PUT or POST */
1.96      frystyk   181: } Context;
1.4       timbl     182: 
1.162     eric      183: PRIVATE int scan_command (SOCKET s, void * param, HTEventType type);
1.164     frystyk   184: 
                    185: PRIVATE HTEvent * ConsoleEvent = NULL;
1.162     eric      186: 
1.106     frystyk   187: #ifndef WWW_WIN_WINDOW
1.118     eric      188: PRIVATE FILE *         OUTPUT = stdout;
1.99      frystyk   189: #endif
1.96      frystyk   190:  
1.106     frystyk   191: PRIVATE InputParser_t parse_command;
                    192: InputParser_t * PInputParser = &parse_command;
1.127     frystyk   193: 
1.128     frystyk   194: /* Net callback handlers */
1.160     frystyk   195: PRIVATE HTNetAfter terminate_handler;
1.127     frystyk   196: 
1.62      frystyk   197: /* ------------------------------------------------------------------------- */
                    198: 
1.162     eric      199: PUBLIC int HTWatch(int id, void * obj, const char * fmt, ...)
                    200: {
                    201:     va_list pArgs;
                    202:     va_start(pArgs, fmt);
                    203:     fprintf(stderr, "id: %x  obj: %p: ", id, obj);
                    204:     return vfprintf(stderr, fmt, pArgs);
                    205: }
                    206: 
1.96      frystyk   207: /*     Create a Context Object
                    208: **     -----------------------
                    209: */
1.104     frystyk   210: PRIVATE Context * Context_new (LineMode *lm, HTRequest *request, LMState state)
1.96      frystyk   211: {
1.112     frystyk   212:     Context * me;
                    213:     if ((me = (Context  *) HT_CALLOC(1, sizeof (Context))) == NULL)
                    214:         HT_OUTOFMEM("Context_new");
1.104     frystyk   215:     me->state = state;
1.96      frystyk   216:     me->request = request;
                    217:     me->lm = lm;
1.116     frystyk   218:     HTRequest_setContext(request, (void *) me); 
                    219:     HTList_addObject(lm->active, (void *) me);
1.72      frystyk   220:     return me;
                    221: }
                    222: 
1.96      frystyk   223: /*     Delete a Context Object
                    224: **     -----------------------
1.72      frystyk   225: */
1.96      frystyk   226: PRIVATE BOOL Context_delete (Context * old)
1.72      frystyk   227: {
1.112     frystyk   228:     HT_FREE(old);
1.72      frystyk   229:     return YES;
                    230: }
                    231: 
1.118     eric      232: PUBLIC LineMode * Context_getLineMode(HTRequest * request)
                    233: {
                    234:     return ((Context *) HTRequest_context(request))->lm;
                    235: }
                    236: 
1.62      frystyk   237: /*
1.96      frystyk   238: **  This function creates a new request object and adds it to the global
1.62      frystyk   239: **  list of active threads
                    240: */
1.130     eric      241: CSDisposition_callback PICSCallback;
1.104     frystyk   242: PRIVATE HTRequest * Thread_new (LineMode * lm, BOOL Interactive, LMState state)
1.62      frystyk   243: {
1.96      frystyk   244:     HTRequest * newreq = HTRequest_new();
                    245:     if (!lm) return NULL;
1.104     frystyk   246:     Context_new(lm, newreq, state);
1.96      frystyk   247:     if (Interactive) HTRequest_setConversion(newreq, lm->presenters, NO);
1.108     frystyk   248:     if (lm->flags & LM_PREEMTIVE) HTRequest_setPreemptive(newreq, YES);
1.104     frystyk   249:     HTRequest_addRqHd(newreq, HT_C_HOST);
1.126     hallam    250:     CSApp_registerReq(newreq, lm->pCSUser, PICSCallback, 
                    251:                      CSApp_callOnBad, (void *)lm);
1.62      frystyk   252:     return newreq;
                    253: }
                    254: 
                    255: /*
1.96      frystyk   256: **  This function deletes all unused request objects
1.62      frystyk   257: */
1.96      frystyk   258: PRIVATE void Thread_cleanup (LineMode * lm)
1.62      frystyk   259: {
1.96      frystyk   260:     if (lm && lm->active) {
                    261:        HTList * cur = lm->active;
                    262:        Context * pres;
                    263:        while ((pres = (Context *) HTList_nextObject(cur))) {
1.104     frystyk   264:            if (pres->state&LM_DONE && pres->state&LM_INACTIVE) {
                    265:                if ((HTList_removeObject(lm->active, pres)) == NO)
1.118     eric      266:                    HTTrace("NOT FOUND\n");
1.96      frystyk   267:                HTRequest_delete(pres->request);
                    268:                Context_delete(pres);
                    269:                cur = lm->active;
                    270:            }
                    271:        }
1.62      frystyk   272:     }
                    273: }
                    274: 
                    275: /*
                    276: **  This function deletes the whole list of active threads.
                    277: */
1.96      frystyk   278: PRIVATE void Thread_deleteAll (LineMode * lm)
1.62      frystyk   279: {
1.96      frystyk   280:     if (lm && lm->active) {
                    281:        HTList * cur = lm->active;
                    282:        Context * pres;
                    283:        while ((pres = (Context *) HTList_nextObject(cur))) {
1.104     frystyk   284:            if (pres->request) {
                    285:                HTRequest_delete(pres->request);
                    286:                Context_delete(pres);
                    287:            }
1.62      frystyk   288:        }
1.96      frystyk   289:        HTList_delete(lm->active);
                    290:        lm->active = NULL;
1.62      frystyk   291:     }
                    292: }
                    293: 
1.96      frystyk   294: /*     Create a Line Mode Object
                    295: **     -------------------------
                    296: */
                    297: PRIVATE LineMode * LineMode_new (void)
                    298: {
                    299:     LineMode * me;
1.167     frystyk   300:     if ((me = (LineMode *) HT_CALLOC(1, sizeof(LineMode))) == NULL)    
1.112     frystyk   301:        HT_OUTOFMEM("LineMode_new");
1.147     frystyk   302:     me->cwd = HTGetCurrentDirectoryURL();
1.96      frystyk   303:     me->active = HTList_new();
1.115     frystyk   304:     me->console = HTRequest_new();
                    305:     Context_new(me, me->console, LM_UPDATE);
1.104     frystyk   306:     me->trace = SHOW_ALL_TRACE;
1.167     frystyk   307:     me->timer = -1;
1.124     eric      308:     me->pCSUser = 0;
1.134     eric      309:     if (!(me->pView = HTView_create("'nother Window", 25, 80, me)))
1.130     eric      310:        return 0;
1.96      frystyk   311:     return me;
                    312: }
                    313: 
                    314: /*     Delete a Line Mode Object
                    315: **     -------------------------
                    316: */
                    317: PRIVATE BOOL LineMode_delete (LineMode * lm)
                    318: {
                    319:     if (lm) {
                    320:        Thread_deleteAll(lm);
                    321:        HTPresentation_deleteAll(lm->presenters);
                    322:        HTHistory_delete(lm->history);
1.112     frystyk   323:        HT_FREE(lm->cwd);
1.96      frystyk   324:        if (lm->logfile) HTLog_close();
1.124     eric      325:        if (lm->pCSUser)
                    326:            CSLoadedUser_remove(lm->pCSUser);
1.118     eric      327:        HTView_destroy(lm->pView);
1.106     frystyk   328: #ifndef WWW_WIN_WINDOW
1.118     eric      329:        if (OUTPUT && OUTPUT != stdout) fclose(OUTPUT);
1.99      frystyk   330: #endif
1.147     frystyk   331:        HText_freeAll();        /* Free all loaded documents */
1.112     frystyk   332:        HT_FREE(lm);
1.96      frystyk   333:        return YES;
                    334:     }
                    335:     return NO;
                    336: }
                    337: 
1.118     eric      338: PUBLIC HTRequest * LineMode_getConsole(LineMode * pLm)
                    339: {
                    340:     return pLm->console;
                    341: }
                    342: 
                    343: PUBLIC HTView * LineMode_getView(LineMode * pLm)
                    344: {
                    345:     return pLm ? pLm->pView : 0;
                    346: }
                    347: 
1.124     eric      348: PRIVATE BOOL LineMode_load(LineMode * lm, HTParentAnchor * anchor, 
                    349:                           char * url, BOOL preemptive, HTRequest ** pPReq)
                    350: {
                    351:     char * fullURL;
                    352:     HTParentAnchor * pAnchor;
                    353: 
1.139     frystyk   354:     *pPReq = Thread_new(lm, YES, LM_UPDATE);
1.124     eric      355:     if (preemptive)
                    356:         HTRequest_setPreemptive(*pPReq, YES);
                    357:     if (anchor)
                    358:        return HTLoadRelative(url, anchor, *pPReq);
                    359:     fullURL = HTParse(url, lm->cwd, PARSE_ALL);
                    360:     pAnchor = (HTParentAnchor *) HTAnchor_findAddress(fullURL);
                    361:     HT_FREE(fullURL);
                    362:     return HTLoadAnchor((HTAnchor *) pAnchor, *pPReq);
                    363: }
                    364: 
1.96      frystyk   365: PRIVATE void Cleanup (LineMode * me, int status)
                    366: {
                    367:     if (HTAlert_interactive())    /* Terminate with a LF if not interactive */
1.118     eric      368:        OutputData(me->pView, "\n");
1.126     hallam    369:     CSLoadedUser_deleteAll();
1.133     eric      370:     CSApp_unregisterApp();
1.152     eric      371: 
1.96      frystyk   372:     LineMode_delete(me);
1.149     frystyk   373:     HTProfile_delete();
1.170   ! frystyk   374: #ifdef HT_MEMLOG
1.168     eric      375:     HTMemLog_close();
1.170   ! frystyk   376: #endif
        !           377: 
1.96      frystyk   378: #ifdef VMS
                    379:     exit(status ? status : 1);
                    380: #else
                    381:     exit(status ? status : 0);
                    382: #endif
                    383: }
1.7       secret    384: 
                    385: /*
1.100     frystyk   386: ** Get size of the output screen. Stolen from less.
1.40      frystyk   387: */
1.90      frystyk   388: PRIVATE void scrsize (int * p_height, int * p_width)
1.7       secret    389: {
1.120     frystyk   390: #if defined(HAVE_IOCTL) && defined(HAVE_WINSIZE)
1.96      frystyk   391:     register char *s;
1.153     frystyk   392:     /* int ioctl(); - henrik */
1.96      frystyk   393:     struct winsize w;
                    394:     if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0)
                    395:        *p_height = w.ws_row;
                    396:     else if ((s = getenv("LINES")) != NULL)
                    397:        *p_height = atoi(s);
                    398:     else
                    399:        *p_height = SCREEN_HEIGHT;
                    400:     
                    401:     if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
                    402:        *p_width = w.ws_col;
                    403:     else if ((s = getenv("COLUMNS")) != NULL)
                    404:        *p_width = atoi(s);
                    405:     else
                    406:        *p_width = 80;
1.120     frystyk   407: #else
                    408:     *p_height = SCREEN_HEIGHT;
                    409:     *p_width = SCREEN_WIDTH;
                    410: #endif /* HAVE_IOCTL && HAVE_WINSIZE */
1.7       secret    411: }
                    412: 
1.50      frystyk   413: #ifdef CATCH_SIG
                    414: #include <signal.h>
                    415: /*                                                                 SetSignal
                    416: **  This function sets up signal handlers. This might not be necessary to
                    417: **  call if the application has its own handlers.
                    418: */
1.90      frystyk   419: PRIVATE void SetSignal (void)
1.50      frystyk   420: {
                    421:     /* On some systems (SYSV) it is necessary to catch the SIGPIPE signal
                    422:     ** when attemting to connect to a remote host where you normally should
                    423:     ** get `connection refused' back
                    424:     */
                    425:     if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
1.118     eric      426:        if (PROT_TRACE) HTTrace("HTSignal.... Can't catch SIGPIPE\n");
1.50      frystyk   427:     } else {
1.118     eric      428:        if (PROT_TRACE) HTTrace("HTSignal.... Ignoring SIGPIPE\n");
1.50      frystyk   429:     }
1.170   ! frystyk   430: 
        !           431: #ifdef HT_MEMLOG
        !           432:     HTMemLog_flush();
        !           433: #endif
        !           434: 
1.50      frystyk   435: }
                    436: #endif /* CATCH_SIG */
                    437: 
1.96      frystyk   438: /*  Print version information
                    439: **  -------------------------
                    440: */
1.118     eric      441: PRIVATE void VersionInfo (LineMode * lm)
1.96      frystyk   442: {
1.160     frystyk   443:     HTView * pView = lm ? lm->pView : NULL;
1.118     eric      444:     OutputData(pView, "\n\nW3C Reference Software\n\n");
                    445:     OutputData(pView, "\tW3C Line Mode Browser version %s.\n", APP_VERSION);
                    446:     OutputData(pView, "\tW3C Reference Library version %s.\n\n",HTLib_version());
1.160     frystyk   447:     OutputData(pView, "Please send feedback to <libwww@w3.org>\n");
1.96      frystyk   448: }
1.7       secret    449: 
1.40      frystyk   450: /*     Reference_List
                    451: **     --------------
1.96      frystyk   452: **     Print out a list of HyperText References from current document
1.40      frystyk   453: */
1.96      frystyk   454: PRIVATE void Reference_List (LineMode * lm, BOOL titles)
1.40      frystyk   455: {
1.50      frystyk   456:     int refs = HText_sourceAnchors(HTMainText);
                    457:     if (refs <= 0) {
1.118     eric      458:        OutputData(lm->pView, "\n\nThere are no references from this document.\n\n");
1.40      frystyk   459:     } else {
1.68      frystyk   460:        int cnt;
1.118     eric      461:        OutputData(lm->pView, "\n*** References from this document ***\n");
1.50      frystyk   462:        for (cnt=1; cnt<=refs; cnt++) {
1.146     frystyk   463:            HTLink * link =
                    464:                HTAnchor_mainLink((HTAnchor*)HText_childNumber(HTMainText,cnt));
                    465:            HTAnchor * dest = HTLink_destination(link);
1.50      frystyk   466:            HTParentAnchor * parent = HTAnchor_parent(dest);
                    467:            char * address =  HTAnchor_address(dest);
1.120     frystyk   468:            const char * title = titles ? HTAnchor_title(parent) : NULL;
1.118     eric      469:            OutputData(lm->pView, reference_mark, cnt);
                    470:            OutputData(lm->pView, "%s%s\n",
1.50      frystyk   471:                    ((HTAnchor*)parent!=dest) && title ? "in " : "",
1.40      frystyk   472:                    (char *)(title ? title : address));
1.112     frystyk   473:            HT_FREE(address);
1.40      frystyk   474:        }
1.106     frystyk   475: #ifndef WWW_WIN_WINDOW
1.99      frystyk   476:        fflush(OUTPUT);
                    477: #endif
1.40      frystyk   478:     }
                    479: }      
1.1       timbl     480: 
1.96      frystyk   481: /*     History_List
                    482: **     ------------
1.68      frystyk   483: **     Display a history list of nodes visited during the session.
1.1       timbl     484: */
1.96      frystyk   485: PRIVATE void History_List (LineMode * lm)
                    486: {
                    487:     int current = HTHistory_position(lm->history);
                    488:     int max = HTHistory_count(lm->history);
1.70      frystyk   489:     int cnt;
1.118     eric      490:     OutputData(lm->pView, "\n  Documents you have visited: ");
1.70      frystyk   491:     if (max > MAX_HISTORY) {
                    492:        max = MAX_HISTORY;
1.118     eric      493:        OutputData(lm->pView, "(truncated)\n");
1.70      frystyk   494:     } else
1.118     eric      495:        OutputData(lm->pView, "\n");
1.70      frystyk   496:     for (cnt=1; cnt<=max; cnt++) {
1.96      frystyk   497:        HTAnchor *anchor = HTHistory_list(lm->history, cnt);
1.70      frystyk   498:        char *address = HTAnchor_address(anchor);
                    499:        HTParentAnchor *parent = HTAnchor_parent(anchor);
1.120     frystyk   500:        const char *title = HTAnchor_title(parent);
1.118     eric      501:        OutputData(lm->pView, "%s R %d\t%s%s\n",
1.70      frystyk   502:               (cnt==current) ? "*" : " ",
                    503:               cnt,
1.68      frystyk   504:               ((HTAnchor*)parent!=anchor) && title ? "in " : "",
                    505:               title ? title : address);
1.112     frystyk   506:        HT_FREE(address);
1.70      frystyk   507:     }
1.118     eric      508:     OutputData(lm->pView, "\n");
1.1       timbl     509: }
                    510: 
1.94      frystyk   511: /*     Prompt for answer and get text back. Reply text is either NULL on
1.120     frystyk   512: **     error or a dynamic string which the caller must HT_FREE.
1.94      frystyk   513: */
1.120     frystyk   514: PRIVATE char * AskUser (HTRequest * request, const char * Msg,
                    515:                        const char * deflt)
1.94      frystyk   516: {
                    517:     char buffer[200];
                    518:     char *reply = NULL;
1.118     eric      519:     HTTrace("%s ", Msg ? Msg : "UNKNOWN");
1.94      frystyk   520:     if (deflt)
1.118     eric      521:        HTTrace("(RETURN for [%s]) ", deflt);
1.94      frystyk   522: 
                    523: #ifndef NO_STDIO
                    524:     if (!fgets(buffer, 200, stdin))
                    525:        return NULL;                         /* NULL string on error, Henrik */
                    526:     buffer[strlen(buffer)-1] = '\0';                   /* Overwrite newline */
                    527:     if (*buffer)
                    528:        StrAllocCopy(reply, buffer);
                    529:     else if (deflt)
                    530:        StrAllocCopy(reply, deflt);
                    531: #endif
                    532:     return reply;
                    533: }
                    534: 
1.120     frystyk   535: PRIVATE BOOL confirm (HTRequest * request, const char * Msg)
1.94      frystyk   536: {
1.96      frystyk   537:     char response[4];
1.118     eric      538:     HTTrace("%s (y/n) ", Msg ? Msg : "UNKNOWN");
1.94      frystyk   539: #ifndef NO_STDIO
1.96      frystyk   540:     if (fgets(response, 4, stdin))                /* get reply, max 3 chars */
1.94      frystyk   541: #endif
1.96      frystyk   542:     {
                    543:        char *ptr = response;
                    544:        while (*ptr) {
                    545:            if (*ptr == '\n') {
                    546:                *ptr = '\0';
                    547:                break;
                    548:            }
                    549:            *ptr = TOUPPER(*ptr);
                    550:            ptr++;
                    551:        }
                    552:        return (!strcmp(response, "YES") || !strcmp(response, "Y")) ? YES : NO;
1.94      frystyk   553:     }
1.96      frystyk   554:     return NO;
1.94      frystyk   555: }
1.1       timbl     556: 
1.96      frystyk   557: /*     MakeCommandLine
                    558: **     ---------------
1.40      frystyk   559: **     Generate the Prompt line and flush it to the user
1.1       timbl     560: */
1.96      frystyk   561: PRIVATE void MakeCommandLine (LineMode * lm, BOOL is_index)
1.40      frystyk   562: {
1.70      frystyk   563:     /* First Line */
1.69      frystyk   564:     if (HTAnchor_hasChildren(HTMainAnchor)) {
1.40      frystyk   565:        int refs = HText_sourceAnchors(HTMainText);
1.69      frystyk   566:        if (refs>1)
1.118     eric      567:            OutputData(lm->pView, "1-%d, ", refs);
1.69      frystyk   568:        else
1.118     eric      569:            OutputData(lm->pView, "1, ");       
1.40      frystyk   570:     }
1.70      frystyk   571:     if (HText_canScrollUp(HTMainText)) {
1.118     eric      572:        OutputData(lm->pView, "Top, ");
                    573:        OutputData(lm->pView, "Up, ");
1.70      frystyk   574:     }
                    575:     if (HText_canScrollDown(HTMainText)) {
1.118     eric      576:        OutputData(lm->pView, "BOttom, ");
                    577:        OutputData(lm->pView, "Down or <RETURN> for more,");
1.70      frystyk   578:     }
1.69      frystyk   579: 
1.70      frystyk   580:     /* Second Line */
1.118     eric      581:     OutputData(lm->pView, "\n");
1.96      frystyk   582:     if (HTHistory_canBacktrack(lm->history))
1.118     eric      583:        OutputData(lm->pView, "Back, ");
1.96      frystyk   584:     if (HTHistory_canForward(lm->history))
1.118     eric      585:        OutputData(lm->pView, "Forward, ");
1.70      frystyk   586:     if (is_index)
1.118     eric      587:        OutputData(lm->pView, "FIND <keywords>, ");
                    588:     OutputData(lm->pView, "Quit, or Help: ");  
1.44      frystyk   589:     fflush(stdout);                      /* For use to flush out the prompt */
1.40      frystyk   590:     return;
                    591: }
1.1       timbl     592: 
1.40      frystyk   593: /*
1.150     frystyk   594: **  PUT the current document to the destination specified by the user
1.110     frystyk   595: **  Returns the result of the load function.
                    596: */
1.150     frystyk   597: PRIVATE int PutAnchor (LineMode * lm, HTRequest * request)
1.110     frystyk   598: {
1.150     frystyk   599:     char * dest = AskUser(request, "Destination: ", NULL);
1.110     frystyk   600: 
1.150     frystyk   601:     /*
                    602:     ** If user has typed a destination then create a new request object and
                    603:     ** start the PUT operation. The destination is taken relative to the
                    604:     ** current location.
                    605:     */
                    606:     if (dest) {
                    607:        HTRequest * new_request = Thread_new(lm, YES, LM_UPDATE);
1.158     frystyk   608:        HTPutDocumentRelative(HTMainAnchor, dest, HTMainAnchor, new_request);
1.150     frystyk   609:        HT_FREE(dest);
                    610:     }
1.158     frystyk   611:     return YES;
1.150     frystyk   612: }
1.110     frystyk   613: 
1.150     frystyk   614: /*
                    615: **  Delete the current document.
                    616: */
                    617: PRIVATE int DeleteAnchor (LineMode * lm, HTRequest * request)
                    618: {
                    619:     int status = HT_INTERNAL;
                    620:     BOOL doit = confirm(request, "Delete the current document?");
                    621:     if (doit) {
                    622:        HTRequest * new_request = Thread_new(lm, YES, LM_UPDATE);
                    623:        status = HTDeleteAnchor((HTAnchor *) HTMainAnchor, new_request);
1.110     frystyk   624:     }
                    625:     return status;
                    626: }
                    627: 
                    628: /*
1.40      frystyk   629: **  This function puts up a stream to a file in order to save a document. This
                    630: **  is activated by '>', '>>' or '>!' from the prompt line.
1.1       timbl     631: */
1.90      frystyk   632: PRIVATE BOOL SaveOutputStream (HTRequest * req, char * This, char * Next)
1.40      frystyk   633: {
                    634:     FILE *fp;
                    635:     char *fname;
                    636:     char *fmode;
                    637:     
                    638:     /* Checks if file exists. Can be overruled by using '>!' */
                    639:     if (*(This+1) == '>') {                               /* Append to file */
1.74      frystyk   640:        fmode = "ab";
1.40      frystyk   641:        fname = *(This+2) ? (This+2) : Next;
                    642:     } else if (*(This+1) == '!') {
1.74      frystyk   643:        fmode = "wb";                                      /* Overwrite file */
1.40      frystyk   644:        fname = *(This+2) ? (This+2) : Next;
                    645:     } else {                                           /* File name follows */
1.74      frystyk   646:        fmode = "wb";
1.40      frystyk   647:        fname = *(This+1) ? (This+1) : Next;
                    648:        if (fname) {                                   /* See if file exists */
                    649:            if ((fp = fopen(fname, "r")) != NULL) {
                    650:                fclose(fp);
1.94      frystyk   651:                if (!confirm(req, "File exists - overwrite?"))
1.92      frystyk   652:                    return NO;
1.40      frystyk   653:            }
                    654:        }
                    655:     }
                    656:     if (!fname)                                               /* No file name given */
                    657:        return NO;
                    658:     if ((fp = fopen(fname, fmode)) == NULL) {
1.118     eric      659:        if (SHOW_MSG) HTTrace("Can't access file (%s)\n", fname);
1.40      frystyk   660:        return NO;
                    661:     }
1.109     frystyk   662:     HTRequest_setOutputStream(req, HTFWriter_new(req, fp, NO));
1.118     eric      663:     if (SHOW_MSG) HTTrace("Saving to file `%s\'\n", fname);
1.58      frystyk   664:     return (HTLoadAnchor((HTAnchor*) HTMainAnchor, req) != HT_WOULD_BLOCK);
1.40      frystyk   665: }
1.1       timbl     666: 
1.124     eric      667: CSError_t LoadedUsersCallback(CSUser_t * pCSUser, int index, void * pVoid)
1.121     eric      668: {
                    669:     LineMode * lm = (LineMode *)pVoid;
1.124     eric      670:     OutputData(lm->pView, "%d: %s\n", index, CSUser_name(pCSUser));
                    671:     return CSError_OK;
1.121     eric      672: }
                    673: 
1.124     eric      674: CSError_t UserListCallback(char * username, char * url, int index, void * pVoid)
1.121     eric      675: {
                    676:     LineMode * lm = (LineMode *)pVoid;
                    677:     OutputData(lm->pView, "%d: %s %s\n", index, username, url);
1.124     eric      678:     return CSError_OK;
1.121     eric      679: }
                    680: 
                    681: PRIVATE BOOL ShowPICSUsers(LineMode * lm)
                    682: {
                    683:     OutputData(lm->pView, "Loaded users:\n");
1.124     eric      684:     CSLoadedUser_enum(&LoadedUsersCallback, (void *)lm);
1.121     eric      685:     OutputData(lm->pView, "Listed users:\n");
                    686:     CSUserList_enum(&UserListCallback, (void *)lm);
                    687:     return YES;
                    688: }
                    689: 
1.126     hallam    690: PRIVATE int PICS_userCallback(CSUser_t * pCSUser, void * pVoid)
                    691: {
                    692:     LineMode * lm = (LineMode *)pVoid;
                    693:     char * userName;
                    694:     char * password = NULL;
1.132     eric      695:     HTAlertCallback *cbf;
1.126     hallam    696:     int ret;
                    697:     HTAlertPar * reply;
                    698: 
1.132     eric      699:     if (lm->noPICSPasswords) {
                    700:         lm->pCSUser = pCSUser;
                    701:        return 0;
                    702:     }
                    703:     if (!(cbf = HTAlert_find(HT_A_USER_PW)))
1.126     hallam    704:         return -1;
                    705:     reply = HTAlert_newReply();
                    706:     userName = CSUser_name(pCSUser);
                    707:     if ((ret = (*cbf)(lm->console, HT_A_USER_PW, 
                    708:                      HT_MSG_NULL, userName, NULL, reply))) {
                    709:         userName = HTAlert_replyMessage(reply);
                    710:         password = HTAlert_replySecret(reply);
                    711:     }
                    712:     HTAlert_deleteReply(reply);
                    713:     if (!ret) {
                    714:         HTTrace("PICS set user *canceled*.\n");
                    715:        return -1;
                    716:     }
                    717:     ret = -1;
                    718:     if (!userName)
                    719:        HTTrace("PICS cannot set to no name.\n");
                    720:     else if (CSUser_checkPassword(pCSUser, password) == NO)
                    721:         HTTrace("PICS password was not valid.\n");
                    722:     else {
                    723:         ret = 0;
                    724:        lm->pCSUser = pCSUser;
                    725:     }
                    726:     HT_FREE(userName);
                    727:     HT_FREE(password);
                    728:     return ret;
                    729: }
                    730: 
1.124     eric      731: PRIVATE BOOL SetPICSUser(LineMode * lm, char * userName)
1.121     eric      732: {
                    733:     char * password = NULL;
1.132     eric      734:     HTAlertCallback *cbf;
1.121     eric      735:     BOOL ret;
1.124     eric      736:     HTAlertPar * reply;
1.121     eric      737: 
1.132     eric      738:     if (!(cbf = HTAlert_find(HT_A_USER_PW)))
1.124     eric      739:         return NO;
                    740:     reply = HTAlert_newReply();
1.125     eric      741:     if ((ret = (*cbf)(lm->console, HT_A_USER_PW, 
                    742:                      HT_MSG_NULL, userName, NULL, reply))) {
1.124     eric      743:         userName = HTAlert_replyMessage(reply);
                    744:         password = HTAlert_replySecret(reply);
                    745:     }
                    746:     HTAlert_deleteReply(reply);
1.125     eric      747:     if (!ret) {
                    748:         HTTrace("PICS set user *canceled*.\n");
                    749:        return NO;
                    750:     }
1.126     hallam    751:     ret = NO;
1.124     eric      752:     if (!userName)
                    753:        HTTrace("Canceled.\n");
1.126     hallam    754:     else if (!(lm->pCSUser = CSApp_registerUserByName(userName, password))) {
1.124     eric      755:         char * url;
                    756:         if ((url = CSUserList_findURL(userName)) == NULL)
                    757:            HTTrace("PICS user \"%s\" is unknown.\n", userName);
1.130     eric      758:        else if (!CSLoadedUser_load(url, lm->cwd))
1.124     eric      759:            HTTrace("Can't load PICS user \"%s\".\n", userName);
                    760:        else if ((CSLoadedUser_find(userName)) == NO)
                    761:            HTTrace("PICS user \"%s\" not found in \"%s\".\n", userName, url);
1.126     hallam    762:        else if (!(lm->pCSUser = CSApp_registerUserByName(userName, password)))
1.124     eric      763:            HTTrace("Failed to set PICS user to \"%s\".\n", userName);
1.126     hallam    764:        ret = YES;
1.124     eric      765:        HT_FREE(url);
                    766:     }
                    767:     HT_FREE(userName);
                    768:     HT_FREE(password);
                    769:     return ret;
                    770: }
                    771: 
                    772: PRIVATE BOOL LoadPICSUser(LineMode * lm, char * url)
                    773: {
                    774:     CSUser_t * pCSUser;
                    775:     if (!(pCSUser = CSLoadedUser_load(url, lm->cwd)))
                    776:         return NO;
1.126     hallam    777:     lm->pCSUser = pCSUser;
                    778:     return YES;
1.124     eric      779: }
                    780: 
1.126     hallam    781: CSError_t PICSCallback(HTRequest* pReq, CSLabel_t * pCSLabel, 
                    782:                       CSUser_t * pCSUser, CSError_t disposition, void * pVoid)
1.124     eric      783: {
                    784:     LineMode * lm = (LineMode *)pVoid;
1.126     hallam    785:     char * mesg;
1.124     eric      786:     switch (disposition) {
1.126     hallam    787:         case CSError_RATING_RANGE:
                    788:             {
                    789:            char * labelStr = CSLabel_getRatingStr(pCSLabel);
                    790:            char * userStr = CSUser_getRatingStr(pCSUser);
1.135     eric      791:            char * anchorStr = HTAnchor_address((HTAnchor*)HTRequest_anchor(pReq));
1.126     hallam    792:             OutputData(lm->pView, "PICS user %s is not allowed to see document: %s\n", 
1.135     eric      793:                       CSUser_name(pCSUser), anchorStr);
1.126     hallam    794:             OutputData(lm->pView, "  %s's \"%s\" rating for service %s (%s) did not include %s\n", 
                    795:                       CSUser_name(pCSUser), 
                    796:                       CSLabel_getRatingName(pCSLabel),
                    797:                       CSLabel_getServiceName(pCSLabel), 
                    798:                       userStr, labelStr);
                    799:            HT_FREE(userStr);
                    800:            HT_FREE(labelStr);
1.135     eric      801:            HT_FREE(anchorStr);
1.126     hallam    802:            }
                    803:            return disposition;
                    804:         case CSError_BUREAU_NONE: mesg="label bureau was not contacted"; break;
1.134     eric      805:         case CSError_RATING_VALUE: mesg="value"; break;
1.126     hallam    806:         case CSError_RATING_MISSING: mesg="rating not found"; break;
1.134     eric      807:         case CSError_SINGLELABEL_MISSING: mesg="no single-labels found"; break;
1.126     hallam    808:         case CSError_SERVICE_MISSING: mesg="service not available";break;
                    809:         case CSError_SERVICE_NONE: mesg="no services available for document"; break;
                    810:         case CSError_RATING_NONE: mesg="no ratings in a service"; break;
                    811:         case CSError_BAD_DATE: mesg="labels were out of date"; break;
                    812:         default:HTTrace("PICSCallback: odd error code: %d\n", disposition); return disposition;
1.124     eric      813:     }
1.126     hallam    814:     OutputData(lm->pView, "PICS disallowed document: %s\n", mesg);
1.124     eric      815:     return disposition;
1.121     eric      816: }
                    817: 
1.62      frystyk   818: /* ------------------------------------------------------------------------- */
                    819: /*                             EVENT FUNCTIONS                              */
                    820: /* ------------------------------------------------------------------------- */
1.1       timbl     821: 
1.89      frystyk   822: /*     parse_command
1.76      frystyk   823: **     ------------
1.89      frystyk   824: **      Given the user's input, deal with it as necessary.
1.40      frystyk   825: **     Any Command which works returns from the routine. If nothing
                    826: **     works then a search or error message down at the bottom.
1.76      frystyk   827: **
                    828: **     Returns         HT_ERROR        Error has occured or we quit
                    829: **                     HT_OK           Call back was OK
1.1       timbl     830: */
1.162     eric      831: PRIVATE int parse_command (char* choice, SOCKET s, HTRequest *req, HTEventType type)
1.101     frystyk   832: {
1.68      frystyk   833:     char * the_choice=NULL;                       /* preserved user command */
                    834:     char * token=NULL;                             /* First word of command */
                    835:     char * this_command;                             /* token and following */
1.40      frystyk   836:     char * next_word;                                        /* Second word */
                    837:     char * other_words;                                /* Second word and following */
1.14      frystyk   838:     BOOL is_index = HTAnchor_isIndex(HTMainAnchor);
1.48      frystyk   839:     BOOL found = YES;
1.68      frystyk   840:     BOOL OutSource = NO;                           /* Output source, YES/NO */
1.76      frystyk   841:     int status = YES;
1.114     frystyk   842:     HTRequest * cur_req = NULL;
                    843:     Context * cur_context = NULL;
                    844:     LineMode * lm = NULL;
1.101     frystyk   845: 
1.114     frystyk   846:     cur_req = req;
1.106     frystyk   847:     cur_context = (Context *) HTRequest_context(req);
                    848:     lm = cur_context->lm;
1.40      frystyk   849: 
                    850:     StrAllocCopy (the_choice, choice);                /* Remember it as is, */
1.91      frystyk   851:     if (*the_choice && the_choice[strlen(the_choice)-1] == '\n') /* final \n */
1.40      frystyk   852:        the_choice[strlen(the_choice)-1] = '\0';
1.14      frystyk   853:     
1.68      frystyk   854:     token = strtok (choice, " \t\n\r");              /* Tokenize user input */
1.40      frystyk   855:     this_command = the_choice;
1.68      frystyk   856:     if (token) {
1.40      frystyk   857:        next_word = strtok (NULL, " \t\n\r");
                    858:        other_words = the_choice + (next_word - choice);
1.14      frystyk   859:     }
1.40      frystyk   860:     else
                    861:        goto down;                              /* Empty input : scroll down */
                    862:     
                    863:     /* Process Command */
                    864:   loop:
1.68      frystyk   865:     switch (TOUPPER(*token)) {
1.40      frystyk   866:       case '0':
                    867:       case '1':
                    868:       case '2':
                    869:       case '3':
                    870:       case '4':
                    871:       case '5':
                    872:       case '6':
                    873:       case '7':
                    874:       case '8':
                    875:       case '9':
1.68      frystyk   876:        {
                    877:            int  ref_num;
                    878:            sscanf(token,"%d",&ref_num);
                    879:            if (ref_num>0 && ref_num<=HText_sourceAnchors(HTMainText)) {
                    880:                HTChildAnchor *source = HText_childNumber(HTMainText, ref_num);
                    881:                if (source) {
1.146     frystyk   882:                    HTLink * link = HTAnchor_mainLink((HTAnchor *) source);
                    883:                    HTAnchor * destination = HTLink_destination(link);
                    884:                    req = Thread_new(lm, YES, LM_UPDATE);                   
1.69      frystyk   885: 
                    886:                    /* Continous browsing, so we want Referer field */
1.90      frystyk   887:                    HTRequest_setParent(req,
                    888:                                        HTAnchor_parent((HTAnchor*)source));
1.123     frystyk   889:                    HTLoadAnchor(destination, req);
1.68      frystyk   890:                } else {
1.76      frystyk   891:                    status = NO;                                /* No anchor */
1.68      frystyk   892:                }
1.45      frystyk   893:            } else {
1.68      frystyk   894:                if (SHOW_MSG)
1.118     eric      895:                    HTTrace("Warning: Invalid Reference Number: (%d)\n",
1.68      frystyk   896:                            ref_num);
1.44      frystyk   897:            }
1.40      frystyk   898:        }
                    899:        break;
                    900:        
                    901:       case 'B':                
1.68      frystyk   902:        if (CHECK_INPUT("BACK", token)) {         /* Return to previous node */
1.96      frystyk   903:            if (HTHistory_canBacktrack(lm->history)) {
1.104     frystyk   904:                req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96      frystyk   905:                status = HTLoadAnchor(HTHistory_back(lm->history), req);
1.40      frystyk   906:            } else {
1.118     eric      907:                OutputData(lm->pView, "\nThis is the first document in history list\n");
1.40      frystyk   908:            }
1.68      frystyk   909:        } else if (CHECK_INPUT("BOTTOM", token)) {      /* Scroll to bottom  */
1.40      frystyk   910:            HText_scrollBottom(HTMainText);
1.48      frystyk   911:        } else
                    912:            found = NO;
1.40      frystyk   913:        break;
                    914:        
1.51      frystyk   915:       case 'C':
1.120     frystyk   916: #ifdef HAVE_CHDIR
1.68      frystyk   917:        if (CHECK_INPUT("CD", token)) {        /* Change working directory ? */
1.40      frystyk   918:            goto lcd;
1.64      frystyk   919:        } else
1.120     frystyk   920: #endif /* HAVE_CHDIR */
1.69      frystyk   921:        if (CHECK_INPUT("CLEAR", token)) {             /* Clear History list */
1.96      frystyk   922:            HTHistory_removeFrom(lm->history, 1);
1.69      frystyk   923:        } else
1.48      frystyk   924:            found = NO;
1.40      frystyk   925:        break;
                    926:        
                    927:       case 'D':
1.108     frystyk   928:        if (CHECK_INPUT("DELETE", token)) {                        /* DELETE */
1.150     frystyk   929:            status = DeleteAnchor(lm, req);
1.108     frystyk   930:        } else if (CHECK_INPUT("DOWN", token)) {    /* Scroll down one page  */
1.40      frystyk   931:          down:
                    932:            if (HText_canScrollDown(HTMainText))
                    933:                HText_scrollDown(HTMainText);
1.48      frystyk   934:        } else
                    935:            found = NO;
1.40      frystyk   936:        break;
                    937:        
1.51      frystyk   938:       case 'E':
1.68      frystyk   939:        if (CHECK_INPUT("EDIT", token)) {
1.150     frystyk   940:            status = PutAnchor(lm, req);
1.68      frystyk   941:        } else if (CHECK_INPUT("EXIT", token)) {            /* Quit program? */
1.76      frystyk   942:            status = NO;
1.48      frystyk   943:        } else
                    944:            found = NO;
1.40      frystyk   945:        break;
                    946:        
                    947:       case 'F':                                                 /* Keyword search ? */
1.68      frystyk   948:        if (is_index && CHECK_INPUT("FIND", token)) {
1.40      frystyk   949:          find:
1.47      frystyk   950:            {
                    951:                if (next_word) {
1.104     frystyk   952:                    req = Thread_new(lm, YES, LM_UPDATE);
1.150     frystyk   953:                    status = HTSearchString(other_words,
                    954:                                            (HTAnchor *) HTMainAnchor, req);
1.47      frystyk   955:                }
                    956:            }
1.158     frystyk   957:        } else if (CHECK_INPUT("FLUSH", token)) {        /* Flush file cache */
                    958:            if (confirm(req, "Flush Persistent Cache?") == YES)
                    959:                HTCache_flushAll();
                    960: 
1.69      frystyk   961:        } else if (CHECK_INPUT("FORWARD", token)) {
1.96      frystyk   962:            if (HTHistory_canForward(lm->history)) {
1.104     frystyk   963:                req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96      frystyk   964:                status = HTLoadAnchor(HTHistory_forward(lm->history), req);
1.69      frystyk   965:            } else {
1.118     eric      966:                OutputData(lm->pView, "\nThis is the last document in history list.\n");
1.69      frystyk   967:            }
1.48      frystyk   968:        } else
                    969:            found = NO;
1.40      frystyk   970:        break;
                    971:        
                    972:       case 'G':
1.68      frystyk   973:        if (CHECK_INPUT("GOTO", token)) {                            /* GOTO */
1.124     eric      974:            if (next_word)
                    975:                status = LineMode_load(lm, HTMainAnchor, next_word, NO, &req);
1.48      frystyk   976:        } else
                    977:            found = NO;
1.40      frystyk   978:        break;
                    979:        
                    980:       case '?':
1.124     eric      981:        status = LineMode_load(lm, HTMainAnchor, C_HELP, YES, &req);
1.47      frystyk   982:        break;
1.40      frystyk   983:        
                    984:       case 'H':
1.68      frystyk   985:        if (CHECK_INPUT("HELP", token)) {                    /* help menu, ..*/
1.124     eric      986:            status = LineMode_load(lm, HTMainAnchor, C_HELP, YES, &req);
1.68      frystyk   987:        } else if (CHECK_INPUT("HOME", token)) {                /* back HOME */
1.96      frystyk   988:            if (!HTHistory_canBacktrack(lm->history)) {
1.40      frystyk   989:                HText_scrollTop(HTMainText);
                    990:            } else {
1.104     frystyk   991:                req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96      frystyk   992:                status = HTLoadAnchor(HTHistory_find(lm->history, 1), req);
1.40      frystyk   993:            }
1.48      frystyk   994:        } else
                    995:            found = NO;
1.40      frystyk   996:        break;
                    997:        
                    998:       case 'K':                                                 /* Keyword search ? */
1.68      frystyk   999:        if (is_index && CHECK_INPUT("KEYWORDS", token)) {
1.40      frystyk  1000:            goto find;
1.48      frystyk  1001:        } else
                   1002:            found = NO;
1.40      frystyk  1003:        break;
                   1004:        
                   1005:       case 'L':
1.68      frystyk  1006:        if (CHECK_INPUT("LIST", token)) {            /* List of references ? */
1.96      frystyk  1007:            Reference_List(lm, !OutSource);
1.40      frystyk  1008:        }
1.120     frystyk  1009: #ifdef HAVE_CHDIR
1.68      frystyk  1010:        else if (CHECK_INPUT ("LCD", token)) {         /* Local change dir ? */
1.40      frystyk  1011:          lcd:
                   1012:            if (!next_word) {                            /* Missing argument */
1.118     eric     1013:                OutputData(lm->pView, "\nName of the new local directory missing.\n");
1.47      frystyk  1014:            } else if (chdir (next_word)) {              /* failed : say why */
1.118     eric     1015:                OutputData(lm->pView, "\n  ");
1.40      frystyk  1016:                perror (next_word);
1.47      frystyk  1017:            } else {                /* Success : display new local directory */
1.127     frystyk  1018: #ifdef HAVE_GETCWD
                   1019:                OutputData(lm->pView, "\nLocal directory is now:\n %s\n",
                   1020:                           getcwd (choice, sizeof(choice)));
                   1021: #else
1.120     frystyk  1022: #ifdef HAVE_GETWD
1.118     eric     1023:                OutputData(lm->pView, "\nLocal directory is now:\n %s\n",
1.120     frystyk  1024:                           (char *) getwd (choice));
                   1025: #else
                   1026: #error "This platform doesn't support getwd or getcwd"
1.68      frystyk  1027:                if (SHOW_MSG)
1.120     frystyk  1028:                    HTTrace("This platform doesn't support getwd or getcwd\n");
1.127     frystyk  1029: #endif /* HAVE_GETWD */
1.120     frystyk  1030: #endif /* HAVE_GETCWD */
1.40      frystyk  1031:            }
                   1032:        }
1.120     frystyk  1033: #endif /* HAVE_CHDIR */
1.124     eric     1034:        else if (CHECK_INPUT("LUSER", token)) {      /* List of references ? */
                   1035:            if (next_word) {
                   1036:                LoadPICSUser(lm, next_word);
                   1037:            } else {
                   1038:                HTTrace("URL needed\n");
                   1039:            }
                   1040:        } else
1.48      frystyk  1041:            found = NO;
1.40      frystyk  1042:        break;
                   1043:        
                   1044:       case 'M':
1.68      frystyk  1045:        if (CHECK_INPUT("MANUAL", token)) {              /* Read User manual */
1.124     eric     1046:            status = LineMode_load(lm, HTMainAnchor, MANUAL, YES, &req);
1.158     frystyk  1047:        } else
                   1048:            found = NO;
                   1049:        break;
                   1050:        
                   1051:       case 'O':
                   1052:        if (CHECK_INPUT("OPTIONS", token)) {               /* OPTIONS method */
                   1053:            req = Thread_new(lm, YES, LM_NO_UPDATE);
                   1054:            status = HTOptionsAnchor((HTAnchor*)
                   1055:                                     (HTMainAnchor ? HTMainAnchor:lm->anchor),
                   1056:                                     req);
1.48      frystyk  1057:        } else
                   1058:            found = NO;
1.40      frystyk  1059:        break;
                   1060:        
                   1061:       case 'P':                    
1.68      frystyk  1062:        if (CHECK_INPUT("POST", token)) {
1.151     frystyk  1063:            status = PutAnchor(lm, req);
1.40      frystyk  1064:        }
1.70      frystyk  1065: 
1.120     frystyk  1066: #ifdef HAVE_SYSTEM         
1.96      frystyk  1067:        else if (!lm->host && CHECK_INPUT("PRINT", token)) {
1.40      frystyk  1068:            char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
                   1069:            char * command;
1.62      frystyk  1070:            char * tmplate = (char *) getenv("WWW_PRINT_COMMAND");
1.40      frystyk  1071:            int result;
                   1072:            
1.46      frystyk  1073:            if (!tmplate) tmplate = "www -n -na -p66 '%s' | lpr";
1.126     hallam   1074:            if ((command = (char *) HT_MALLOC(strlen(address)+strlen(tmplate)+20)) == NULL)
1.112     frystyk  1075:                HT_OUTOFMEM("command");
1.46      frystyk  1076:            sprintf(command, tmplate, address);
1.40      frystyk  1077:            result = system(command);
1.112     frystyk  1078:            HT_FREE(address);
                   1079:            HT_FREE(command);
1.118     eric     1080:            if (result) OutputData(lm->pView, "  %s\n  returns %d\n", command, result);
1.40      frystyk  1081:        }
                   1082: #endif
                   1083:        /* this command prints the entire current text to the
                   1084:           terminal's printer; at the end it displays the top of the text */
                   1085: #ifdef SLAVE_PRINTER
                   1086: #define SLAVE_PRINTER_ON  "\033\133\065\151"
                   1087: #define SLAVE_PRINTER_OFF "\033\133\064\151"
                   1088:        
1.68      frystyk  1089:        else if (CHECK_INPUT("PS", token)) {
1.118     eric     1090:            OutputData(lm->pView, "%s",SLAVE_PRINTER_ON);
                   1091:            OutputData(lm->pView, "\f");                           /* Form feed for new page */
1.40      frystyk  1092:            HText_scrollTop(HTMainText);
                   1093:            while(HText_canScrollDown(HTMainText)) {
                   1094:                HText_scrollDown(HTMainText);
                   1095:            }
1.118     eric     1096:            OutputData(lm->pView, "\f");                           /* Form feed for new page */
                   1097:            OutputData(lm->pView, "%s",SLAVE_PRINTER_OFF);
1.40      frystyk  1098:            HText_scrollTop(HTMainText);
                   1099:        }       
                   1100: #endif
1.68      frystyk  1101:        else if (CHECK_INPUT("PUT", token)) {
1.151     frystyk  1102:            status = PutAnchor(lm, req);
1.62      frystyk  1103:        } else
1.48      frystyk  1104:            found = NO;
1.40      frystyk  1105:        break;
                   1106:        
                   1107:       case 'Q':                                                   /* Quit program ? */
1.68      frystyk  1108:        if (CHECK_INPUT("QUIT", token)) {
1.47      frystyk  1109: 
1.40      frystyk  1110:            /*  JFG 9/7/92, following a complaint of 'q' mis-typed for '1'.
                   1111:                JFG Then made optional because I hate it !!!
                   1112:                TBL made it only affect remote logged on users. 921122 */
                   1113:            
1.96      frystyk  1114:            if (lm->host && (strcasecomp(token, "quit") != 0) ) {
1.118     eric     1115:                OutputData(lm->pView, "\n Please type \"quit\" in full to leave www.\n");
1.76      frystyk  1116:            } else {
                   1117:                HTNet_killAll();                        /* Kill all requests */
                   1118:                status = NO;
                   1119:            }
1.48      frystyk  1120:        } else
                   1121:            found = NO;
1.40      frystyk  1122:        break;
                   1123:        
                   1124:       case 'R':        
1.68      frystyk  1125:        if (CHECK_INPUT("RECALL", token)) {
1.96      frystyk  1126:            if (HTHistory_count(lm->history) <= 1) {
1.118     eric     1127:                OutputData(lm->pView, "\n  No other documents to recall.\n");
1.47      frystyk  1128:            } else {
                   1129:                /* Previous node number exists, or does the user just */
                   1130:                /* require a list of nodes visited? */
1.69      frystyk  1131:                if (next_word) {        
                   1132:                    int cnt;
                   1133:                    if ((cnt = atoi(next_word)) > 0) {
1.104     frystyk  1134:                        req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96      frystyk  1135:                        status = HTLoadAnchor(HTHistory_find(lm->history,cnt), req);
1.47      frystyk  1136:                    } else {
1.68      frystyk  1137:                        if (SHOW_MSG)
1.118     eric     1138:                            HTTrace("Bad command (%s), for list of commands type help\n", this_command);
1.47      frystyk  1139:                    }
                   1140:                } else {
1.96      frystyk  1141:                    History_List(lm);
1.47      frystyk  1142:                }
1.40      frystyk  1143:            }
1.68      frystyk  1144:        } else if (CHECK_INPUT("REFRESH", token)) {
1.50      frystyk  1145:            HText_setStale(HTMainText);                     /* Force refresh */
                   1146:            HText_refresh(HTMainText);                     /* Refresh screen */
1.156     frystyk  1147: 
                   1148:        } else if (CHECK_INPUT("REVALIDATE", token)) {
                   1149:            req = Thread_new(lm, YES, LM_NO_UPDATE);
                   1150: 
                   1151:            /*
                   1152:            **  Add a end-to-end validator to the request
                   1153:            */
                   1154:            HTRequest_setReloadMode(req, HT_CACHE_END_VALIDATE);
                   1155:            status = HTLoadAnchor((HTAnchor*) (HTMainAnchor ? HTMainAnchor : 
                   1156:                                               lm->anchor), req);
1.68      frystyk  1157:        } else if (CHECK_INPUT("RELOAD", token)) {
1.104     frystyk  1158:            req = Thread_new(lm, YES, LM_NO_UPDATE);
1.155     frystyk  1159: 
                   1160:            /*
                   1161:            **  Make sure that we do a complete flush of the cache
                   1162:            */
                   1163:            HTRequest_setReloadMode(req, HT_CACHE_FLUSH);
1.124     eric     1164:            status = HTLoadAnchor((HTAnchor*) (HTMainAnchor ? HTMainAnchor : 
                   1165:                                  lm->anchor), req);
1.48      frystyk  1166:        } else
                   1167:            found = NO;
1.40      frystyk  1168:        break;
                   1169:        
                   1170:       case 'S':                                                       /* TBL 921009 */
1.68      frystyk  1171:        if (CHECK_INPUT("SOURCE", token)) {               /* Apply to source */
1.47      frystyk  1172:            if (next_word) {
                   1173:                OutSource = YES;                 /* Load and print as source */
1.68      frystyk  1174:                token = next_word;                       /* Move up one word */
1.47      frystyk  1175:                next_word = strtok (NULL, " \t\n\r");
1.68      frystyk  1176:                this_command = the_choice + (token - choice);
1.47      frystyk  1177:                other_words = the_choice + (next_word - choice);
                   1178:                goto loop;                             /* Go treat as before */
                   1179:            }
1.68      frystyk  1180:        } else if (CHECK_INPUT("SET", token)) {                    /* config */
1.93      frystyk  1181:            HTList * rules = HTRule_global();
                   1182:            HTRule_parseLine(rules, other_words);
1.48      frystyk  1183:        } else
                   1184:            found = NO;
1.40      frystyk  1185:        break;
                   1186:        
                   1187:       case 'T':
1.68      frystyk  1188:        if (CHECK_INPUT("TOP", token)) {                   /* Return to top  */
1.40      frystyk  1189:            HText_scrollTop(HTMainText);
1.48      frystyk  1190:        } else
                   1191:            found = NO;
1.40      frystyk  1192:        break;
                   1193:        
                   1194:       case 'U':
1.68      frystyk  1195:        if (CHECK_INPUT("UP", token)) {               /* Scroll up one page  */
1.40      frystyk  1196:            HText_scrollUp(HTMainText);
1.121     eric     1197:        } else if (CHECK_INPUT("USER", token)) {
                   1198:            if (next_word) {
                   1199:                        if (!strcasecomp(next_word, "?")) {
                   1200:                                ShowPICSUsers(lm);
1.124     eric     1201:                                SetPICSUser(lm, 0);
1.121     eric     1202:                        } else {
1.124     eric     1203:                                SetPICSUser(lm, next_word);
1.121     eric     1204:                        }
                   1205:            } else {
1.124     eric     1206:                SetPICSUser(lm, 0);
1.121     eric     1207:                }
                   1208:        } else 
1.48      frystyk  1209:            found = NO;
1.40      frystyk  1210:        break;
                   1211:        
                   1212:       case 'V':
1.155     frystyk  1213:        if (CHECK_INPUT("VALIDATE", token)) {              /* Cache validate */
                   1214:            req = Thread_new(lm, YES, LM_NO_UPDATE);
                   1215: 
                   1216:            /*
                   1217:            **  Add a validator to the request
                   1218:            */
                   1219:            HTRequest_setReloadMode(req, HT_CACHE_VALIDATE);
                   1220:            status = HTLoadAnchor((HTAnchor*) (HTMainAnchor ? HTMainAnchor : 
                   1221:                                               lm->anchor), req);
                   1222:        } else if (CHECK_INPUT("VERBOSE", token)) {  /* Switch verbose mode  */
1.96      frystyk  1223:            WWWTRACE = WWWTRACE ? 0 : lm->trace;
1.118     eric     1224:            OutputData(lm->pView, "\n  Verbose mode %s.\n", WWWTRACE ? "ON":"OFF");
1.68      frystyk  1225:        } else if (CHECK_INPUT("VERSION", token)) {               /* Version */
1.118     eric     1226:            VersionInfo(lm);
1.48      frystyk  1227:        } else
                   1228:            found = NO;
1.40      frystyk  1229:        break;
1.160     frystyk  1230: 
                   1231:       case 'W':
                   1232:        if (CHECK_INPUT("WHICH", token)) {     /* Show title/URL of current page */
                   1233:            HTView * pView = lm ? lm->pView : NULL;
                   1234:            char * current_address = HTAnchor_address((HTAnchor *) HTMainAnchor);
                   1235:            const char * title = HTAnchor_title(HTMainAnchor);
                   1236:            if (title)
                   1237:                OutputData(pView, "\n\nYou are reading\n\t`%s\'\nwith address\n\t%s\n\n",
                   1238:                           title, current_address);
                   1239:        } else
                   1240:            found = NO;
                   1241:        break;
1.40      frystyk  1242:        
                   1243:       case 'Z':
1.50      frystyk  1244:        HText_setStale(HTMainText);                         /* Force refresh */
                   1245:        HText_refresh(HTMainText);                         /* Refresh screen */
1.76      frystyk  1246:        HTNet_killAll();                                /* Kill all requests */
1.44      frystyk  1247:        break;
1.40      frystyk  1248: 
                   1249:       case '>':
1.96      frystyk  1250:        if (!lm->host) {
1.58      frystyk  1251:            HText *curText = HTMainText;     /* Remember current main vindow */
1.104     frystyk  1252:            req = Thread_new(lm, NO, LM_NO_UPDATE);
1.155     frystyk  1253:            HTRequest_setReloadMode(req, HT_CACHE_FLUSH_MEM);
1.90      frystyk  1254:            if (OutSource) HTRequest_setOutputFormat(req, WWW_SOURCE);
1.76      frystyk  1255:            SaveOutputStream(req, token, next_word);
1.58      frystyk  1256:            HText_select(curText);
1.40      frystyk  1257:        }
                   1258:        break;
1.1       timbl    1259:        
1.50      frystyk  1260: #ifdef GOT_PIPE
1.40      frystyk  1261:       case '|':
1.96      frystyk  1262:        if (!lm->host) {                                   /* Local only!!!! */
1.40      frystyk  1263:            char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
                   1264:            char * command;
                   1265:            int result;
1.112     frystyk  1266:            if ((command = (char *) HT_MALLOC(strlen(address) +strlen(this_command)+30)) == NULL)
                   1267:                HT_OUTOFMEM("command");
1.40      frystyk  1268:            sprintf(command, "www %s \"%s\" %s", 
                   1269:                    OutSource ? "-source" : "-n -na -p", address,this_command);
1.118     eric     1270:            OutputData(lm->pView, "Command: %s\n", command);
1.40      frystyk  1271:            result = system(command);
1.118     eric     1272:            if (result) OutputData(lm->pView, "  %s  returns %d\n", command, result);
1.112     frystyk  1273:            HT_FREE(command);
                   1274:            HT_FREE(address);
1.14      frystyk  1275:        }
1.47      frystyk  1276:        break;
1.40      frystyk  1277: #endif
                   1278:            
1.120     frystyk  1279: #ifdef HAVE_SYSTEM
1.40      frystyk  1280:       case '!':
1.96      frystyk  1281:        if (!lm->host) {                                      /* Local only! */
1.40      frystyk  1282:            int result;
1.118     eric     1283:            if (SHOW_MSG) HTTrace("Executing `%s\'\n", this_command);
1.40      frystyk  1284:            result = system(strchr(this_command, '!') + 1);
1.118     eric     1285:            if (result) OutputData(lm->pView, "  %s  returns %d\n",
1.96      frystyk  1286:                                 strchr(this_command, '!') + 1, result);
1.1       timbl    1287:        }
1.47      frystyk  1288:        break;
1.120     frystyk  1289: #endif /* HAVE_SYSTEM */
1.40      frystyk  1290:       default:
1.48      frystyk  1291:        found = NO;
                   1292:        break;
                   1293:     } /* Switch on 1st character */
                   1294: 
                   1295:     if (!found) {
1.68      frystyk  1296:        if (is_index && *token) {  /* No commands, search keywords */
1.47      frystyk  1297:            next_word = other_words = this_command;
1.48      frystyk  1298:            found = YES;
1.47      frystyk  1299:            goto find;
                   1300:        } else {             
1.68      frystyk  1301:            if (SHOW_MSG)
1.118     eric     1302:                HTTrace("Bad command (%s), for list of commands type help\n", this_command);
1.47      frystyk  1303:        }
1.48      frystyk  1304:     }
1.96      frystyk  1305:     MakeCommandLine(lm, is_index);
1.112     frystyk  1306:     HT_FREE(the_choice);
1.96      frystyk  1307: 
                   1308:     /* 
                   1309:     ** If we have created a new Request and is to update the history list then
                   1310:     ** we can set the inactive bit on this request object.
                   1311:     */
1.104     frystyk  1312:     if (cur_req == req)
                   1313:        cur_context->state |= LM_NO_UPDATE;
1.115     frystyk  1314:     else
1.104     frystyk  1315:        cur_context->state |= LM_INACTIVE;    
1.76      frystyk  1316:     return (status==YES) ? HT_OK : HT_ERROR;
1.40      frystyk  1317: }
                   1318: 
1.96      frystyk  1319: /*     readConsole
                   1320: **     -----------
                   1321: **     non-blocking read of the WIN32 console. EGP
                   1322: */
1.97      frystyk  1323: 
1.106     frystyk  1324: #ifdef WWW_WIN_CONSOLE
1.89      frystyk  1325: PUBLIC BOOL readConsole(HANDLE conIn, char* buf, int len, int* pRed)
                   1326: {
                   1327:     DWORD recordIndex, bufferIndex, toRead, red;
                   1328:     PINPUT_RECORD pInput;
                   1329: 
                   1330:     /* grab the pending input records (keystrokes plus other garbage). */
                   1331:     GetNumberOfConsoleInputEvents(conIn, &toRead);
                   1332:     if (len < (int)toRead)     /* we'll get the rest on the next pass(es). */
                   1333:     toRead = len;
1.112     frystyk  1334:     if ((pInput = (PINPUT_RECORD) HT_MALLOC(toRead * sizeof(INPUT_RECORD))) == NULL)   /* room for n input records */
1.89      frystyk  1335:        return (FALSE);
                   1336:     ReadConsoleInput(conIn, pInput, toRead, &red);
                   1337: 
                   1338:     for (recordIndex = bufferIndex = 0; recordIndex < red; recordIndex++) {
                   1339:        /* grab all keydown events */
1.97      frystyk  1340: #if 1
                   1341:         KEY_EVENT_RECORD keyEvent = pInput[recordIndex].Event.KeyEvent;     /* only used if EventType == KEY_EVENT */
                   1342:        if (pInput[recordIndex].EventType == KEY_EVENT && keyEvent.bKeyDown) {
                   1343:            while (keyEvent.wRepeatCount && keyEvent.uChar.AsciiChar) {
                   1344:                /* stuff the buffer with the keys */
                   1345:                buf[bufferIndex] = keyEvent.uChar.AsciiChar;
                   1346:                if (buf[bufferIndex] == '\r')
                   1347:                    buf[bufferIndex] = '\n';
                   1348:                if (buf[bufferIndex] == '\b')
1.118     eric     1349:                    OutputData(lm->pView, "\b ");
                   1350:                OutputData(lm->pView, "%c", buf[bufferIndex]);
1.97      frystyk  1351:                bufferIndex++;
                   1352:                keyEvent.wRepeatCount--;
                   1353:            }
                   1354:        }
                   1355: #else
                   1356:        if (pInput[recordIndex].EventType == KEY_EVENT && pInput[recordIndex].Event.KeyEvent.bKeyDown) {
                   1357:            while (pInput[recordIndex].Event.KeyEvent.wRepeatCount && pInput[recordIndex].Event.KeyEvent.uChar.AsciiChar) {
                   1358:                /* stuff the buffer with the keys */
                   1359:                buf[bufferIndex] = pInput[recordIndex].Event.KeyEvent.uChar.AsciiChar;
                   1360:                if (buf[bufferIndex] == '\r')
                   1361:                    buf[bufferIndex] = '\n';
                   1362:                if (buf[bufferIndex] == '\b')
1.118     eric     1363:                    OutputData(lm->pView, "\b ");
                   1364:                OutputData(lm->pView, "%c", buf[bufferIndex]);
1.97      frystyk  1365:                bufferIndex++;
                   1366:                pInput[recordIndex].Event.KeyEvent.wRepeatCount--;
                   1367:            }
                   1368:        }
                   1369: #endif
                   1370: 
1.89      frystyk  1371:     }
                   1372: 
1.112     frystyk  1373:     HT_FREE(pInput);
1.97      frystyk  1374:     *pRed = bufferIndex;               /* actual characters stuck into buffer */
1.89      frystyk  1375:     return (TRUE);
                   1376: }
1.106     frystyk  1377: #endif /* WWW_WIN_CONSOLE */
1.89      frystyk  1378: 
1.96      frystyk  1379: /*     bufferInput
                   1380: **     -----------
                   1381: **     Read available characters from buf into stat. buf maybe bigger or
                   1382: **     smaller than stat.
                   1383: */
1.162     eric     1384: PUBLIC int bufferInput (char* buf, int len, SOCKET s, HTRequest * req, HTEventType type)
1.89      frystyk  1385: {
                   1386:     static char stat[RESPONSE_LENGTH];
                   1387:     static int iStat = 0;
                   1388:     static int ignoreNext = 0;
                   1389:     int iBuf;
                   1390:     for (iBuf = 0; iBuf < len; iBuf++) {
                   1391:        switch (buf[iBuf]) {
                   1392:            case '\r':
                   1393:            case '\n':
                   1394:                if (ignoreNext)
                   1395:                    ignoreNext = 0;
                   1396:                else {
                   1397:                    int ret;
                   1398:                    stat[iStat] = 0;
                   1399:                    iStat = 0;
1.162     eric     1400:                    if ((ret = (*PInputParser)(stat, s, req, type)) != HT_OK)
1.89      frystyk  1401:                        return (ret);
                   1402:                }
                   1403:                break;
                   1404:            case '\b':
1.96      frystyk  1405:                if (iStat) /* don't worry about ignoreNext as iStat will be 0*/
1.89      frystyk  1406:                    iStat--;
                   1407:                break;
                   1408:            default:
                   1409:                if (!ignoreNext)
                   1410:                    stat[iStat++] = buf[iBuf];
                   1411:        }
                   1412:        if (iStat == sizeof(stat)) {
1.118     eric     1413:            HTTrace("Read Console... BUFFER OVERRUN\n");
1.89      frystyk  1414:            iStat = 0;
                   1415:            ignoreNext = 1;
                   1416:        }
                   1417:     }
                   1418:     return (HT_OK);
                   1419: }
                   1420: 
1.164     frystyk  1421: /*     timeout_handler
                   1422: **     ---------------
                   1423: **     This function is registered to handle timeout in select eventloop
                   1424: */
                   1425: PRIVATE int timeout_handler (SOCKET s, void * param, HTEventType type)
                   1426: {
                   1427:     if (!HTAlert_interactive()) {
                   1428:        HTRequest * req = (HTRequest *) param;
                   1429:        Context * context = (Context *) HTRequest_context(req);
                   1430:        LineMode * lm = context->lm;
                   1431:        if (SHOW_MSG) HTTrace("Request timed out");
                   1432:        HTNet_killAll();
                   1433:        Cleanup(lm, -1);
                   1434:     }
1.165     eric     1435:     if (HTNet_count() > 0)
                   1436:        if (SHOW_MSG) HTTrace(".");
1.164     frystyk  1437:     return 0;
                   1438: }
                   1439: 
1.162     eric     1440: PRIVATE int scan_command (SOCKET s, void * param, HTEventType type)
1.89      frystyk  1441: {
1.162     eric     1442:     HTRequest * req = (HTRequest *)param;
1.91      frystyk  1443:     /* buf happens to == eatText's buffer but not neccesary */
                   1444:     static char buf[RESPONSE_LENGTH];
1.162     eric     1445: #ifdef WWW_MSWINDOWS
1.89      frystyk  1446:     int red;
                   1447:     int ret;
1.164     frystyk  1448: #endif
                   1449: 
                   1450:     /* Handle any timeout here */
                   1451:     if (type == HTEvent_TIMEOUT) return timeout_handler (s, param, type);
1.91      frystyk  1452: 
1.164     frystyk  1453: #ifdef WWW_MSWINDOWS
1.162     eric     1454:     while(1) {
                   1455: #ifdef WWW_WIN_CONSOLE
                   1456:        if (!readConsole((HANDLE)s, buf, sizeof(buf), &red)) {
                   1457:         if (PROT_TRACE) HTTrace("Read Console... READ ERROR\n");
                   1458:            return HT_ERROR;
                   1459:        }
                   1460: #endif /* WWW_WIN_CONSOLE */
                   1461:        if (!red) return (HT_OK);
                   1462:        ret = bufferInput(buf, red, s, req, type);
                   1463:        if (ret != HT_OK) return (ret);
                   1464:     }
                   1465: #else /* WWW_MSWINDOWS */
1.89      frystyk  1466:     if (!fgets(buf, sizeof(buf), stdin))                 /* Read User Input */
1.106     frystyk  1467:         return HT_ERROR;                                     /* Exit if EOF */
1.162     eric     1468:     return ((*PInputParser)(buf, s, req, type));
                   1469: #endif /* !WWW_MSWINOWS */
1.89      frystyk  1470: }
1.40      frystyk  1471: 
1.76      frystyk  1472: /*     terminate_handler
                   1473: **     -----------------
1.96      frystyk  1474: **     This function is registered to handle the result of the request
1.1       timbl    1475: */
1.160     frystyk  1476: PRIVATE int terminate_handler (HTRequest * request, HTResponse * response,
                   1477:                               void * param, int status) 
1.40      frystyk  1478: {
1.96      frystyk  1479:     Context * context = (Context *) HTRequest_context(request);
1.121     eric     1480:     LineMode * lm;
                   1481:     BOOL is_index;
                   1482: 
1.151     frystyk  1483:     if (!context)
                   1484:         return HT_OK;
1.121     eric     1485:     lm = context->lm;
1.146     frystyk  1486:     if (context->state == LM_IGNORE) return HT_OK;
1.157     eric     1487:     if (CSApp_unregisterReq(request) == NO && lm->pCSUser)
1.126     hallam   1488:         HTTrace("PICS request not found\n");
1.121     eric     1489:     is_index = HTAnchor_isIndex(HTMainAnchor);
1.40      frystyk  1490:     if (status == HT_LOADED) {
1.96      frystyk  1491: 
1.155     frystyk  1492:        /*
                   1493:        **  Make sure that we have selected the HText object. This is normally
                   1494:        **  done by the HText interface but may have been avoided by the mem
                   1495:        **  cache filter
                   1496:        */
                   1497:        {
                   1498:            HTParentAnchor * parent = HTRequest_anchor(request);
                   1499:            HTChildAnchor * child = HTRequest_childAnchor(request);
                   1500:            HText * document =  HTAnchor_document(parent);
                   1501:            if (child && (HTAnchor *) child != (HTAnchor *) parent)
                   1502:                HText_selectAnchor(document, child);
                   1503:            else
                   1504:                HText_select(document);
1.165     eric     1505:            HTRequest_forceFlush(request);
1.155     frystyk  1506:        }
                   1507: 
                   1508:        /* Should we output a command line? */
1.96      frystyk  1509:        if (HTAlert_interactive()) {
                   1510:            HText_setStale(HTMainText);
                   1511:            MakeCommandLine(lm, is_index);
                   1512:        } else {
                   1513:            if (lm->flags & LM_REFS) Reference_List(lm, NO);
                   1514:            Cleanup(lm, 0);
                   1515:        }
1.69      frystyk  1516: 
                   1517:        /* Record new history if we have not moved around in the old one */
1.96      frystyk  1518:        if (context->state & LM_UPDATE)
                   1519:            HTHistory_replace(lm->history, (HTAnchor *) HTMainAnchor);
1.69      frystyk  1520: 
1.40      frystyk  1521:        /* Now generate the new prompt line as a function of the result */
                   1522:        if (!HText_canScrollDown(HTMainText) &&
                   1523:            !HTAnchor_hasChildren(HTMainAnchor) && !is_index &&
1.96      frystyk  1524:            (!HTHistory_canBacktrack(lm->history))) {
1.91      frystyk  1525:            return HT_OK;
1.40      frystyk  1526:        }
1.96      frystyk  1527: 
1.134     eric     1528:     } else { /* No page loaded so sit around and wait for a go command */
1.166     eric     1529:        /*      was MakeCommandLine(lm, is_index); */
                   1530:        /*
                   1531:        **      stolen from above
                   1532:        */
                   1533:        if (HTAlert_interactive()) {
                   1534: /*         HText_setStale(HTMainText); */
                   1535:            MakeCommandLine(lm, is_index);
                   1536:        } else {
                   1537:            if (lm->flags & LM_REFS) Reference_List(lm, NO);
                   1538:            Cleanup(lm, 0);
                   1539:        }
                   1540: 
1.76      frystyk  1541:     }
1.96      frystyk  1542:     context->state |= LM_DONE;
                   1543:     Thread_cleanup(lm);
                   1544:     if (!HTAlert_interactive()) Cleanup(lm, -1);
1.76      frystyk  1545:     return HT_OK;
1.40      frystyk  1546: }
1.1       timbl    1547: 
1.40      frystyk  1548: /* ------------------------------------------------------------------------- */
                   1549: /*                               MAIN PROGRAM                               */
                   1550: /* ------------------------------------------------------------------------- */
1.1       timbl    1551: 
1.90      frystyk  1552: int main (int argc, char ** argv)
1.40      frystyk  1553: {
1.68      frystyk  1554:     int                status = 0;     
                   1555:     int                arg;                                      /* Index into argv */
                   1556:     HTChunk *  keywords = NULL;                        /* From command line */
                   1557:     int                keycnt = 0;
1.116     frystyk  1558:     HTRequest *        request = NULL;
1.101     frystyk  1559:     LineMode * lm;
1.121     eric     1560:     char *      picsUser = NULL;
1.141     eric     1561: 
1.96      frystyk  1562:     /* Starts Mac GUSI socket library */
                   1563: #ifdef GUSI
1.75      frystyk  1564:     GUSISetup(GUSIwithSIOUXSockets);
                   1565:     GUSISetup(GUSIwithInternetSockets);
                   1566: #endif
                   1567: 
                   1568: #ifdef __MWERKS__ /* STR */
                   1569:     InitGraf((Ptr) &qd.thePort); 
                   1570:     InitFonts(); 
                   1571:     InitWindows(); 
                   1572:     InitMenus(); TEInit(); 
                   1573:     InitDialogs(nil); 
                   1574:     InitCursor();
                   1575:     SIOUXSettings.asktosaveonclose = false;
                   1576:     argc=ccommand(&argv);
                   1577: #endif
                   1578: 
1.68      frystyk  1579:     /* HWL 18/7/94: patch from agl@glas2.glas.apc.org (Anton Tropashko) */
1.40      frystyk  1580: #ifdef CYRILLIC
                   1581:     arc.locale=0; arc.encoding=0; arc.i_encoding=0; doinull();
1.1       timbl    1582: #endif
                   1583: 
1.170   ! frystyk  1584: #ifdef HT_MEMLOG
        !          1585:     HTMemLog_open(DEFAULT_MEMLOG, 8192, YES);
1.168     eric     1586:     HTTraceData_setCallback(HTMemLog_callback);
1.170   ! frystyk  1587: #endif
        !          1588: 
1.149     frystyk  1589:     /* Initiate W3C Reference Library with a client profile */
                   1590:     HTProfile_newClient(APP_NAME, APP_VERSION);
1.150     frystyk  1591:     
1.163     frystyk  1592:     /* FOR THE MOMENT */
                   1593:     HTCacheMode_setEnabled(NO);
                   1594:     
1.150     frystyk  1595:     /* It's confusing to have progress notofications in linemode browser */
                   1596:     HTAlert_delete(HTProgress);
1.117     frystyk  1597: 
1.149     frystyk  1598:     /* Add the default HTML parser to the set of converters */
                   1599:     {
                   1600:        HTList * converters = HTFormat_conversion();
                   1601:        HTMLInit(converters);
                   1602:     }
1.142     eric     1603: 
1.108     frystyk  1604:     /* Create a new Line Mode object */
1.153     frystyk  1605:     lm = LineMode_new();
1.115     frystyk  1606:     request = Thread_new(lm, NO, LM_UPDATE);
1.96      frystyk  1607: 
                   1608:     /* Scan command Line for parameters */
                   1609:     for (arg=1; arg<argc ; arg++) {
1.40      frystyk  1610:        if (*argv[arg] == '-') {
                   1611: 
                   1612:            /* - alone => filter */
1.96      frystyk  1613:            if (argv[arg][1] == '\0') {
                   1614:                lm->flags |= LM_FILTER;
1.94      frystyk  1615:                HTAlert_setInteractive(NO);
1.40      frystyk  1616:            
1.96      frystyk  1617:            /* non-interactive */
                   1618:            } else if (!strcmp(argv[arg], "-n")) {
                   1619:                HTAlert_setInteractive(NO);
1.40      frystyk  1620: 
                   1621:            /* from -- Initial represntation (only with filter) */
1.96      frystyk  1622:            } else if (!strcmp(argv[arg], "-from")) {
                   1623:                lm->format = (arg+1 < argc && *argv[arg+1] != '-') ?
                   1624:                    HTAtom_for(argv[++arg]) : WWW_HTML;
                   1625:                HTAlert_setInteractive(NO);
1.40      frystyk  1626: 
1.96      frystyk  1627:            /* to -- Final representation */
                   1628:            } else if (!strcmp(argv[arg], "-to")) {
                   1629:                HTFormat format = (arg+1 < argc && *argv[arg+1] != '-') ?
                   1630:                    HTAtom_for(argv[++arg]) : DEFAULT_FORMAT;
1.115     frystyk  1631:                HTRequest_setOutputFormat(request, format);
1.96      frystyk  1632:                HTAlert_setInteractive(NO);
                   1633: 
                   1634:            /* reformat html */
                   1635:            } else if (!strcmp(argv[arg], "-reformat")) {
1.115     frystyk  1636:                HTRequest_setOutputFormat(request, WWW_HTML);
1.96      frystyk  1637:                lm->flags |= LM_REFORMAT;
                   1638:                HTAlert_setInteractive(NO);
                   1639: 
                   1640:            /* List References */
                   1641:            } else if (!strncmp(argv[arg], "-list", 5)) {
                   1642:                lm->flags |= LM_REFS;
                   1643:                HTAlert_setInteractive(NO);
                   1644: 
1.100     frystyk  1645:            /* original output */
1.96      frystyk  1646:            } else if (!strcmp(argv[arg], "-raw")) {
1.115     frystyk  1647:                HTRequest_setOutputFormat(request, WWW_RAW);
1.96      frystyk  1648:                HTAlert_setInteractive(NO);
                   1649: 
                   1650:            /* source please */
                   1651:            } else if (!strcmp(argv[arg], "-source")) {
1.115     frystyk  1652:                HTRequest_setOutputFormat(request, WWW_SOURCE);
1.96      frystyk  1653:                HTAlert_setInteractive(NO);
                   1654: 
                   1655:            /* HEAD method */
                   1656:            } else if (!strcasecomp(argv[arg], "-head")) {
1.115     frystyk  1657:                HTRequest_setMethod(request, METHOD_HEAD);
                   1658:                HTRequest_setOutputFormat(request, WWW_MIME);
1.96      frystyk  1659:                HTAlert_setInteractive(NO);
                   1660: 
1.100     frystyk  1661:            /* output filename */
1.96      frystyk  1662:            } else if (!strcmp(argv[arg], "-o")) { 
                   1663:                lm->outputfile = (arg+1 < argc && *argv[arg+1] != '-') ?
                   1664:                    argv[++arg] : DEFAULT_OUTPUT_FILE;
                   1665:                HTAlert_setInteractive(NO);
                   1666: 
                   1667:            /* print version and exit */
                   1668:            } else if (!strcmp(argv[arg], "-version")) { 
1.119     frystyk  1669:                VersionInfo(lm);
1.96      frystyk  1670:                Cleanup(lm, 0);
                   1671: 
                   1672:            /* -? or -help: show the command line help page */
                   1673:            } else if (!strcmp(argv[arg],"-?") || !strcmp(argv[arg],"-help")) {
                   1674:                lm->anchor = (HTParentAnchor *) HTAnchor_findAddress(L_HELP);
                   1675:                keycnt = 1;
1.40      frystyk  1676: 
                   1677: #ifdef CYRILLIC
                   1678:            /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org
                   1679:               (Anton Tropashko) */
                   1680:            } else if (!strcmp(argv[arg], "-koi2alt")) {
1.118     eric     1681:                doia2k(); OutputData(lm->pView, "Ahak2a!");
1.40      frystyk  1682: #endif
                   1683: 
                   1684:            /* Page size */
                   1685:            } else if (!strncmp(argv[arg], "-p", 2)) {
                   1686:                if (*(argv[arg]+2)) {
                   1687:                    if (sscanf(argv[arg]+2, "%d", &HTScreenHeight) < 1)
                   1688:                        HTScreenHeight = -1;            
                   1689:                    else {
                   1690:                        if(HTScreenHeight < MIN_SCREEN_HEIGHT)
                   1691:                            HTScreenHeight = MIN_SCREEN_HEIGHT;
                   1692:                        if(HTScreenHeight > MAX_SCREEN_HEIGHT)
                   1693:                            HTScreenHeight = MAX_SCREEN_HEIGHT;
                   1694:                    }
1.163     frystyk  1695:                } else if (arg+1 < argc && *argv[arg+1] != '-') {
1.40      frystyk  1696:                    if (sscanf(argv[++arg], "%d", &HTScreenHeight) < 1)
                   1697:                        HTScreenHeight = -1;
                   1698:                    else {
                   1699:                        if(HTScreenHeight < MIN_SCREEN_HEIGHT)
                   1700:                            HTScreenHeight = MIN_SCREEN_HEIGHT;
                   1701:                        if(HTScreenHeight > MAX_SCREEN_HEIGHT)
                   1702:                            HTScreenHeight = MAX_SCREEN_HEIGHT;
                   1703:                    }
                   1704:                }
1.1       timbl    1705: 
1.40      frystyk  1706:            /* Page width */
                   1707:            } else if (!strncmp(argv[arg], "-w", 2)) {
                   1708:                if (*(argv[arg]+2)) {
                   1709:                    if (sscanf(argv[arg]+2, "%d", &HTScreenWidth) < 1)
                   1710:                        HTScreenWidth = SCREEN_WIDTH;
1.163     frystyk  1711:                } else if (arg+1 < argc && *argv[arg+1] != '-') {
1.40      frystyk  1712:                    if (sscanf(argv[++arg], "%d", &HTScreenWidth) < 1)
                   1713:                        HTScreenWidth = SCREEN_WIDTH;
1.14      frystyk  1714:                }
1.40      frystyk  1715:                if(HTScreenWidth < MIN_SCREEN_WIDTH)
                   1716:                    HTScreenWidth = MIN_SCREEN_WIDTH;
                   1717:                if(HTScreenWidth > MAX_SCREEN_WIDTH)
                   1718:                    HTScreenWidth = MAX_SCREEN_WIDTH;
                   1719:                    
                   1720:            /* Telnet from */
                   1721:            } else if (!strcmp(argv[arg], "-h")) {
                   1722:                if (arg+1 < argc && *argv[arg+1] != '-') {
1.96      frystyk  1723:                    lm->host = argv[++arg];                 /* Use host name */
1.92      frystyk  1724:                    HTLib_setSecure(YES);                  /* No easy access */
1.14      frystyk  1725:                }
1.40      frystyk  1726: 
1.96      frystyk  1727:            /* log file */
1.40      frystyk  1728:            } else if (!strcmp(argv[arg], "-l")) {
1.96      frystyk  1729:                lm->logfile = (arg+1 < argc && *argv[arg+1] != '-') ?
1.68      frystyk  1730:                    argv[++arg] : DEFAULT_LOG_FILE;
1.51      frystyk  1731: 
1.96      frystyk  1732:            /* rule file */
                   1733:            } else if (!strcmp(argv[arg], "-r")) {
                   1734:                lm->rules = (arg+1 < argc && *argv[arg+1] != '-') ?
                   1735:                    argv[++arg] : DEFAULT_RULE_FILE;
1.68      frystyk  1736: 
1.96      frystyk  1737:            /* timeout -- Change the default request timeout */
                   1738:            } else if (!strcmp(argv[arg], "-timeout")) {
                   1739:                int timeout = (arg+1 < argc && *argv[arg+1] != '-') ?
                   1740:                    atoi(argv[++arg]) : -1;
1.167     frystyk  1741:                if (timeout > 0) lm->timer = timeout;
1.40      frystyk  1742: 
1.121     eric     1743:            /* PICS user */
                   1744:            } else if (!strcmp(argv[arg], "-u")) {
                   1745:                picsUser = (arg+1 < argc && *argv[arg+1] != '-') ?
1.124     eric     1746:                    argv[++arg] : "user";
1.132     eric     1747:            } else if (!strcmp(argv[arg], "-unp")) {
                   1748:                lm->noPICSPasswords = 1;
1.126     hallam   1749: #if 0 /* old version of user list file, still works when enabeled here */
1.124     eric     1750:            /* PICS user list */
                   1751:            } else if (!strcmp(argv[arg], "-ul")) {
                   1752:                picsUserList = (arg+1 < argc && *argv[arg+1] != '-') ?
                   1753:                    argv[++arg] : "users.url";
1.126     hallam   1754: #endif
                   1755:            /* PICS user list */
                   1756:            } else if (!strcmp(argv[arg], "-ul")) {
                   1757:                lm->userList = (arg+1 < argc && *argv[arg+1] != '-') ?
                   1758:                    argv[++arg] : DEFAULT_USERLIST_FILE;
1.121     eric     1759: 
1.126     hallam   1760:            /* PICS mode */
                   1761:            } else if (!strcmp(argv[arg], "-pics")) {
                   1762:                lm->userList = DEFAULT_USERLIST_FILE;
                   1763: 
1.108     frystyk  1764:            /* preemptive or non-preemptive access */
1.50      frystyk  1765:            } else if (!strcmp(argv[arg], "-single")) {
1.115     frystyk  1766:                HTRequest_setPreemptive(request, YES);
1.96      frystyk  1767:                lm->flags |= LM_PREEMTIVE;
1.50      frystyk  1768: 
1.156     frystyk  1769:            /* Disconnected operation */
                   1770:            } else if (!strncmp(argv[arg], "-discon", 7)) {
                   1771:                HTCacheMode_setDisconnected(HT_DISCONNECT_NORMAL);
1.68      frystyk  1772: 
1.96      frystyk  1773:            /* Handling of Expire (cache) */
1.68      frystyk  1774:            } else if (!strncmp(argv[arg], "-x", 2)) { 
1.155     frystyk  1775:                  char *p = argv[arg]+2;
                   1776:                  for(;*p;p++) {
                   1777:                      switch (argv[arg][2]) {
1.68      frystyk  1778:                      case 'i':
1.156     frystyk  1779:                          HTCacheMode_setExpires(HT_EXPIRES_IGNORE);
1.155     frystyk  1780:                          break;
1.68      frystyk  1781:                      case 'n':
1.156     frystyk  1782:                          HTCacheMode_setExpires(HT_EXPIRES_NOTIFY);
1.155     frystyk  1783:                          break;
1.68      frystyk  1784:                      case 'a':
1.156     frystyk  1785:                          HTCacheMode_setExpires(HT_EXPIRES_AUTO);
1.155     frystyk  1786:                          break;
1.68      frystyk  1787:                      default:
1.155     frystyk  1788:                          if (SHOW_MSG)
                   1789:                              HTTrace("Bad parameter (%s) for option -x\n", argv[arg]);
                   1790:                          break;
                   1791:                      }
                   1792:                  }
1.68      frystyk  1793: 
1.40      frystyk  1794:            /* Anchor format */
                   1795:            } else if (!strcmp(argv[arg], "-a")) { 
                   1796:                if (arg+1 < argc && *argv[arg+1] != '-')
                   1797:                    end_reference = argv[++arg];      /* New representation */
                   1798: 
                   1799:            /* Anchor format */
                   1800:            } else if (!strcmp(argv[arg], "-ar")) { 
                   1801:                if (arg+1 < argc && *argv[arg+1] != '-')
                   1802:                    reference_mark = argv[++arg];  /* Change representation */
                   1803: 
                   1804:            /* Anchor format */
                   1805:            } else if (!strcmp(argv[arg], "-as")) { 
                   1806:                if (arg+1 < argc && *argv[arg+1] != '-')
                   1807:                    start_reference = argv[++arg]; /* Change representation */
                   1808: 
                   1809:            /* No anchors */
                   1810:            } else if (!strcmp(argv[arg], "-na")) { 
                   1811:                    display_anchors = NO;
                   1812: 
                   1813: #ifndef NO_DIR_OPTIONS
                   1814:            } else if (!strncmp(argv[arg], "-d", 2)) {
                   1815:                char *p = argv[arg]+2;
                   1816:                for(;*p;p++) {
                   1817:                    switch (argv[arg][2]) {
1.82      frystyk  1818:                      case 'r':HTFile_setDirReadme(HT_DIR_README_NONE); break;
                   1819:                      case 't':HTFile_setDirReadme(HT_DIR_README_TOP); break;
                   1820:                      case 'b':HTFile_setDirReadme(HT_DIR_README_BOTTOM);break;
                   1821:                      case 'n':HTFile_setDirAccess(HT_DIR_FORBID); break;
                   1822:                      case 's':HTFile_setDirAccess(HT_DIR_SELECTIVE); break;
                   1823:                      case 'y':HTFile_setDirAccess(HT_DIR_OK); break;
1.76      frystyk  1824:                      default:
1.68      frystyk  1825:                        if (SHOW_MSG)
1.118     eric     1826:                            HTTrace("Bad parameter (%s) in -d option\n",
1.68      frystyk  1827:                                    argv[arg]);
1.40      frystyk  1828:                    }
1.96      frystyk  1829:                }
1.40      frystyk  1830: #endif
1.1       timbl    1831: 
1.85      frystyk  1832: #ifdef WWWTRACE
1.96      frystyk  1833:            /* trace flags */
1.40      frystyk  1834:            } else if (!strncmp(argv[arg], "-v", 2)) {
1.146     frystyk  1835:                lm->trace = HTSetTraceMessageMask(argv[arg]+2);
1.1       timbl    1836: #endif
1.40      frystyk  1837:            } else {
1.118     eric     1838:                if (SHOW_MSG) HTTrace("Bad Argument (%s)\n", argv[arg]);
1.40      frystyk  1839:            }
                   1840:        } else {           /* If no leading `-' then check for main argument */
1.68      frystyk  1841:            if (!keycnt) {
1.96      frystyk  1842:                char * ref = HTParse(argv[arg], lm->cwd, PARSE_ALL);
                   1843:                lm->anchor = (HTParentAnchor *) HTAnchor_findAddress(ref);
1.79      frystyk  1844:                keycnt = 1;
1.112     frystyk  1845:                HT_FREE(ref);
1.40      frystyk  1846:            } else {               /* Check for successive keyword arguments */
1.79      frystyk  1847:                char *escaped = HTEscape(argv[arg], URL_XALPHAS);
1.68      frystyk  1848:                if (keycnt++ <= 1)
1.104     frystyk  1849:                    keywords = HTChunk_new(128);
1.68      frystyk  1850:                else
1.104     frystyk  1851:                    HTChunk_putc(keywords, ' ');
                   1852:                HTChunk_puts(keywords, HTStrip(escaped));
1.112     frystyk  1853:                HT_FREE(escaped);
1.68      frystyk  1854:            }
1.79      frystyk  1855:        }
                   1856:     }
1.40      frystyk  1857: 
1.96      frystyk  1858: #ifdef CATCH_SIG
                   1859:     SetSignal();
                   1860: #endif
                   1861: 
                   1862:     /* Make home page address */
                   1863:     if (!lm->anchor) lm->anchor = HTHomeAnchor();
                   1864: 
1.149     frystyk  1865:     /* Do we need list of presenters? (external viewers) */
1.94      frystyk  1866:     if (HTAlert_interactive()) {
1.96      frystyk  1867:        lm->presenters = HTList_new();
                   1868:        HTPresenterInit(lm->presenters);
1.115     frystyk  1869:        HTRequest_setConversion(request, lm->presenters, NO);
1.86      frystyk  1870:     }
                   1871: 
1.40      frystyk  1872:     if (HTScreenHeight == -1) {                                /* Default page size */
1.120     frystyk  1873:        if (HTAlert_interactive())
                   1874:            scrsize(&HTScreenHeight, &HTScreenWidth);
                   1875:        else
1.42      frystyk  1876:            HTScreenHeight = 999999;
1.40      frystyk  1877:     }
1.23      frystyk  1878: 
1.149     frystyk  1879:     /* Disable free directory browsing when using telnet host */
1.96      frystyk  1880:     if (lm->host && HTFile_dirAccess() == HT_DIR_OK)
1.82      frystyk  1881:        HTFile_setDirAccess(HT_DIR_SELECTIVE);
1.1       timbl    1882: 
1.40      frystyk  1883:     /* Open output file */
1.94      frystyk  1884:     if (!HTAlert_interactive()) {
1.106     frystyk  1885: #ifndef WWW_WIN_WINDOW
1.96      frystyk  1886:        if (lm->outputfile) {
1.99      frystyk  1887:            if ((OUTPUT = fopen(lm->outputfile, "wb")) == NULL) {
1.118     eric     1888:                if (SHOW_MSG) HTTrace("Can't open `%s'\\n",
1.96      frystyk  1889:                                       lm->outputfile);
1.118     eric     1890:                OUTPUT = stdout;
1.96      frystyk  1891:            }
                   1892:        }
1.115     frystyk  1893:        HTRequest_setOutputStream(request,
                   1894:                                  HTFWriter_new(request, OUTPUT, YES));
1.99      frystyk  1895: #endif
1.58      frystyk  1896: 
1.96      frystyk  1897:        /*
                   1898:        ** To reformat HTML, just put it through a parser running
1.68      frystyk  1899:        ** into a regenerator   tbl 940613
                   1900:        */
1.96      frystyk  1901:        if (lm->flags & LM_REFORMAT) {
                   1902:            HTStructured * html =
1.115     frystyk  1903:                HTMLGenerator(request, NULL, WWW_HTML,
                   1904:                              HTRequest_outputFormat(request),
                   1905:                              HTRequest_outputStream(request));
                   1906:            HTRequest_setOutputStream(request, SGML_new(&HTMLP_dtd, html));
1.40      frystyk  1907:        }
                   1908:     }
                   1909:     
1.96      frystyk  1910:      /* Log file specifed? */
                   1911:     if (lm->logfile) HTLog_open(lm->logfile, YES, YES);
1.1       timbl    1912: 
1.68      frystyk  1913:     /* Just convert formats */
1.96      frystyk  1914:     if (lm->flags & LM_FILTER) {
                   1915: #ifdef STDIN_FILENO
1.115     frystyk  1916:        HTRequest_setAnchor(request, (HTAnchor *) lm->anchor);
                   1917:        HTRequest_setPreemptive(request, YES);
1.162     eric     1918:        HTLoadSocket(STDIN_FILENO, request);
1.95      frystyk  1919: #endif
1.96      frystyk  1920:        Cleanup(lm, 0);
1.40      frystyk  1921:     }
1.96      frystyk  1922: 
                   1923:     /* Set timeout on sockets */
1.167     frystyk  1924:     if (lm->timer < 0) {
                   1925:        lm->timer = HTAlert_interactive() ?
1.96      frystyk  1926:            DEFAULT_I_TIMEOUT : DEFAULT_NI_TIMEOUT;
1.93      frystyk  1927:     }
1.96      frystyk  1928:     /* Set the DNS cache timeout */
                   1929:     HTDNS_setTimeout(3600);
1.121     eric     1930: 
1.146     frystyk  1931:     /* Rule file specified? */
                   1932:     if (lm->rules) {
                   1933:        char * rules = HTParse(lm->rules, lm->cwd, PARSE_ALL);
1.149     frystyk  1934:        if (!HTLoadRules(rules))
1.146     frystyk  1935:            if (SHOW_MSG) HTTrace("Can't access rules\n");
                   1936:        HT_FREE(rules);
                   1937:     }
                   1938: 
                   1939:     /* Set up PICS machinary */
1.126     hallam   1940:     CSApp_registerApp(PICSCallback, CSApp_callOnBad, PICS_userCallback, 
                   1941:                      (void *)lm);
1.151     frystyk  1942:      /* Add our own filter to update the history list */
1.160     frystyk  1943:     HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
1.164     frystyk  1944: 
1.167     frystyk  1945:     /* Should we load a PICS user profile? */
1.124     eric     1946:     if (picsUser && !LoadPICSUser(lm, picsUser))
                   1947:         HTTrace("Unable to load PICS user \"%s\".\n", picsUser);
1.96      frystyk  1948: 
1.126     hallam   1949:     /* PICS user list specified? */
                   1950:     if (lm->userList)
                   1951:         LoadPICSUser(lm, lm->userList);
                   1952: 
                   1953:     /* request was registered in Thread_new before command line parsing
                   1954:        loaded the PICS user, so re-register to give it the correct user */
                   1955:     CSApp_unregisterReq(request);
                   1956:     CSApp_registerReq(request, lm->pCSUser, PICSCallback, 
                   1957:                      CSApp_callOnBad, (void *)lm);
                   1958: 
1.96      frystyk  1959:     /* Start the request */
                   1960:     if (keywords)
1.150     frystyk  1961:        status = HTSearchAnchor(keywords, (HTAnchor *) lm->anchor, request);
1.96      frystyk  1962:     else
1.115     frystyk  1963:        status = HTLoadAnchor((HTAnchor *) lm->anchor, request);
1.96      frystyk  1964: 
1.104     frystyk  1965:     if (keywords) HTChunk_delete(keywords);
1.96      frystyk  1966:     if (status != YES) {
1.118     eric     1967:        if (SHOW_MSG) HTTrace("Couldn't load home page\n");
1.124     eric     1968:        CSApp_unregisterDefaultUser();
                   1969:        CSApp_unregisterApp();
1.96      frystyk  1970:        Cleanup(lm, -1);
1.76      frystyk  1971:     }
1.68      frystyk  1972: 
1.96      frystyk  1973:     /* Set up the rest if we are in interactive mode */
1.94      frystyk  1974:     if (HTAlert_interactive()) {
1.73      frystyk  1975: 
1.96      frystyk  1976:        /* Start History manager */
                   1977:        lm->history = HTHistory_new();
1.73      frystyk  1978: 
1.83      frystyk  1979:        /*
                   1980:        ** Register STDIN as the user socket IF not STDIN is connected to
                   1981:        ** /dev/null or other non-terminal devices
                   1982:        */
1.167     frystyk  1983:        ConsoleEvent = HTEvent_new(scan_command, lm->console, HT_PRIORITY_MAX, lm->timer);
1.82      frystyk  1984: #ifdef STDIN_FILENO
1.83      frystyk  1985:        if (isatty(STDIN_FILENO)) {
1.164     frystyk  1986:            HTEventList_register(STDIN_FILENO, HTEvent_READ, ConsoleEvent);
1.83      frystyk  1987:        }
1.82      frystyk  1988: #else
1.164     frystyk  1989:        HTEventList_register(GetStdHandle(STD_INPUT_HANDLE), HTEvent_READ, ConsoleEvent);
1.82      frystyk  1990: #endif
1.96      frystyk  1991:     }
1.77      frystyk  1992: 
1.96      frystyk  1993:     /* Go into the event loop... */
1.162     eric     1994:     HTEventList_loop(request);
1.73      frystyk  1995: 
1.96      frystyk  1996:     /* Only gets here if event loop fails */
                   1997:     Cleanup(lm, 0);
                   1998:     return 0;
1.14      frystyk  1999: }
1.112     frystyk  2000: 

Webmaster