home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / LYJump.c < prev    next >
C/C++ Source or Header  |  1998-05-02  |  11KB  |  498 lines

  1. #include <HTUtils.h>
  2. #include <tcp.h>
  3. #include <HTAlert.h>
  4. #include <LYUtils.h>
  5. #include <LYStrings.h>
  6. #include <LYGlobalDefs.h>
  7. #include <LYJump.h>
  8. #include <LYKeymap.h>
  9. #include <LYSignal.h>
  10. #include <GridText.h>
  11.  
  12. #include <LYLeaks.h>
  13.  
  14. #ifdef VMS
  15. #include <fab.h>
  16. #endif /* VMS */
  17.  
  18. #define FREE(x) if (x) {free(x); x = NULL;}
  19.  
  20. struct JumpTable *JThead = NULL;
  21.  
  22. PRIVATE int LYCompare PARAMS ((CONST void *e1, CONST void *e2));
  23. PRIVATE unsigned LYRead_Jumpfile PARAMS ((struct JumpTable *jtp));
  24.  
  25. PUBLIC void LYJumpTable_free NOARGS
  26. {
  27.     struct JumpTable *cur = JThead;
  28.     struct JumpTable *next;
  29.  
  30.     while (cur) {
  31.     next = cur->next;
  32.     FREE(cur->msg);
  33.     FREE(cur->file);
  34.     FREE(cur->shortcut);
  35.     if (cur->history) {
  36.         char *shortcut;
  37.         HTList *current = cur->history;
  38.  
  39.         while (NULL != (shortcut = (char *)HTList_nextObject(current))) {
  40.         FREE(shortcut);
  41.         }
  42.         HTList_delete(cur->history);
  43.         cur->history = NULL;
  44.     }
  45.     FREE(cur->table);
  46.     FREE(cur->mp);
  47.     FREE(cur);
  48.     cur = next;
  49.     }
  50.     JThead = NULL;
  51.     return;
  52. }
  53.  
  54. /*
  55.  * Utility for listing shortcuts, making any repeated
  56.  * shortcut the most current in the list. - FM
  57.  */
  58. PUBLIC void LYAddJumpShortcut ARGS2(HTList *, historyp, char *,shortcut)
  59. {
  60.     char *new;
  61.     char *old;
  62.     HTList *cur =  historyp;
  63.  
  64.     if (!historyp || !(shortcut && *shortcut))
  65.     return;
  66.  
  67.     if ((new = (char *)calloc(1, (strlen(shortcut) + 1))) == NULL)
  68.     outofmem(__FILE__, "HTAddJumpShortcut");
  69.     strcpy(new, shortcut);
  70.  
  71.     while (NULL != (old = (char *)HTList_nextObject(cur))) {
  72.     if (!strcmp(old, new)) {
  73.         HTList_removeObject(historyp, old);
  74.         FREE(old);
  75.         break;
  76.     }
  77.     }
  78.     HTList_addObject(historyp, new);
  79.  
  80.     return;
  81. }
  82.  
  83. PUBLIC BOOL LYJumpInit ARGS1 (char *, config)
  84. {
  85.     struct JumpTable *jtp;
  86.     char *cp;
  87.  
  88.     /*
  89.      * Create a JumpTable structure.
  90.      */
  91.     jtp = (struct JumpTable *) calloc(1, sizeof(*jtp));
  92.     if (jtp == NULL) {
  93.     perror("Out of memory in LYJumpInit");
  94.     return FALSE;
  95.     }
  96.  
  97.     /*
  98.      * config is JUMPFILE:path[:optional_key[:optional_prompt]]
  99.      *
  100.      * Skip JUMPFILE.
  101.      */
  102.     cp = strtok(config, ":\n");
  103.     if (!cp) {
  104.     FREE(jtp);
  105.     return FALSE;
  106.     }
  107.  
  108.     /*
  109.      * Get the path.
  110.      */
  111.     cp = strtok(NULL, ":\n");
  112.     if (!cp) {
  113.     FREE(jtp);
  114.     return FALSE;
  115.     }
  116.     StrAllocCopy(jtp->file, cp);
  117.     if (!JThead)
  118.     atexit(LYJumpTable_free);
  119.  
  120.     /*
  121.      * Get the key, if present.
  122.      */
  123.     cp = strtok(NULL, ":\n");
  124.  
  125.     /*
  126.      * If no key, check whether we are resetting the default jumps file.
  127.      */
  128.     if (!cp && JThead) {
  129.     struct JumpTable *jtptmp = JThead;
  130.     jumpfile = jtp->file;
  131.     FREE(jtp);
  132.     while (jtptmp && jtptmp->key)
  133.         jtptmp = jtptmp->next;
  134.     if (!jtptmp)
  135.         return FALSE;
  136.     StrAllocCopy(jtptmp->file, jumpfile);
  137.     StrAllocCopy(jtptmp->msg, jumpprompt);
  138.     return TRUE;
  139.     }
  140.  
  141.     /*
  142.      * If a key is present and we have no default, create one,
  143.      * using the path from config, and the current jumpprompt.
  144.      */
  145.     if (cp && !JThead) {
  146.     JThead = jtp;
  147.     StrAllocCopy(JThead->msg, jumpprompt);
  148.     if (!jumpfile)
  149.         StrAllocCopy(jumpfile, JThead->file);
  150.     jtp = (struct JumpTable *) calloc(1, sizeof(*jtp));
  151.     if (jtp == NULL) {
  152.         perror("Out of memory in LYJumpInit");
  153.         return FALSE;
  154.     }
  155.     StrAllocCopy(jtp->file, JThead->file);
  156.     }
  157.  
  158.     /*
  159.      * Complete the initialization of config.
  160.      */
  161.     if (cp) {
  162.     jtp->key = remap(cp, "JUMP");        /* key is present, (re)map it */
  163.     cp = strtok(NULL, "\n");        /* get prompt, if present */
  164.     if (cp && *cp)
  165.         StrAllocCopy(jtp->msg, cp);     /* prompt is present, load it */
  166.     else
  167.         cp = NULL;
  168.     }
  169.     if (!cp)                     /* no prompt, use default */
  170.     StrAllocCopy(jtp->msg, jumpprompt);
  171.     if (jtp->msg[strlen(jtp->msg)-1] != ' ') /* ensure a trailing space */
  172.     StrAllocCat(jtp->msg, " ");
  173.     jtp->history = HTList_new();
  174.     jtp->next = JThead;
  175.     JThead = jtp;
  176.     return TRUE;
  177. }
  178.  
  179. PUBLIC char *LYJump ARGS1(int, key)
  180. {
  181.     JumpDatum seeking;
  182.     JumpDatum *found;
  183.     static char buf[124];
  184.     char *bp, *cp;
  185.     struct JumpTable *jtp;
  186.     int ch, recall;
  187.     int ShortcutTotal;
  188.     int ShortcutNum;
  189.     BOOLEAN FirstShortcutRecall = TRUE;
  190.  
  191.     if (!JThead)
  192.     return NULL;
  193.     jtp = JThead;
  194.     while (jtp && jtp->key && jtp->key != key)
  195.     jtp = jtp->next;
  196.     if (!jtp) {
  197.     char msg[40];
  198.     sprintf(msg, KEY_NOT_MAPPED_TO_JUMP_FILE, key);
  199.     HTAlert(msg);
  200.     return NULL;
  201.     }
  202.     if (!jtp->table)
  203.     jtp->nel = LYRead_Jumpfile(jtp);
  204.     if (jtp->nel == 0)
  205.     return NULL;
  206.  
  207.     if (!jump_buffer || !(jtp->shortcut && *jtp->shortcut))
  208.     *buf = '\0';
  209.     else if (jtp->shortcut && *jtp->shortcut) {
  210.     if (strlen(jtp->shortcut) > 119)
  211.         jtp->shortcut[119] = '\0';
  212.     strcpy(buf, jtp->shortcut);
  213.     }
  214.  
  215.     ShortcutTotal = (jtp->history ? HTList_count(jtp->history) : 0);
  216.     if (jump_buffer && *buf) {
  217.     recall = ((ShortcutTotal > 1) ? RECALL : NORECALL);
  218.     ShortcutNum = 0;
  219.     FirstShortcutRecall = FALSE;
  220.     } else {
  221.     recall = ((ShortcutTotal >= 1) ? RECALL : NORECALL);
  222.     ShortcutNum = ShortcutTotal;
  223.     FirstShortcutRecall = TRUE;
  224.     }
  225.  
  226.     statusline(jtp->msg);
  227.     if ((ch=LYgetstr(buf, VISIBLE, (sizeof(buf) - 4), recall)) < 0) {
  228.     /*
  229.      * User cancelled the Jump via ^G. - FM
  230.      */
  231.     _statusline(CANCELLED);
  232.     sleep(InfoSecs);
  233.     return NULL;
  234.     }
  235.  
  236. check_recall:
  237.     bp = buf;
  238.     if (toupper(key) == 'G' && strncmp(buf, "o ", 2) == 0)
  239.     bp++;
  240.     bp = LYSkipBlanks(bp);
  241.     if (*bp == '\0' &&
  242.     !(recall && (ch == UPARROW || ch == DNARROW))) {
  243.     /*
  244.      * User cancelled the Jump via a zero-length string. - FM
  245.      */
  246.     *buf = '\0';
  247.     StrAllocCopy(jtp->shortcut, buf);
  248.     _statusline(CANCELLED);
  249.     sleep(InfoSecs);
  250.     return NULL;
  251.     }
  252. #ifdef PERMIT_GOTO_FROM_JUMP
  253.     if (strchr(bp, ':') || strchr(bp, '/')) {
  254.     char *temp=NULL;
  255.  
  256.     LYJumpFileURL = FALSE;
  257.     if (no_goto) {
  258.         *buf = '\0';
  259.         StrAllocCopy(jtp->shortcut, buf);
  260.         _statusline(RANDOM_URL_DISALLOWED);
  261.         sleep(MessageSecs);
  262.         return NULL;
  263.     }
  264.     StrAllocCopy(temp, "Go ");
  265.     StrAllocCat(temp, bp);
  266.     strcpy(buf, temp);
  267.     FREE(temp);
  268.     return(bp=buf);
  269.     }
  270. #endif /* PERMIT_GOTO_FROM_JUMP */
  271.  
  272.     if (recall && ch == UPARROW) {
  273.     if (FirstShortcutRecall) {
  274.         /*
  275.          * Use last Shortcut in the list. - FM
  276.          */
  277.         FirstShortcutRecall = FALSE;
  278.         ShortcutNum = 0;
  279.     } else {
  280.         /*
  281.          * Go back to the previous Shortcut in the list. - FM
  282.          */
  283.         ShortcutNum++;
  284.     }
  285.     if (ShortcutNum >= ShortcutTotal)
  286.         /*
  287.          * Roll around to the last Shortcut in the list. - FM
  288.          */
  289.         ShortcutNum = 0;
  290.     if ((cp=(char *)HTList_objectAt(jtp->history,
  291.                     ShortcutNum)) != NULL) {
  292.         strcpy(buf, cp);
  293.         if (jump_buffer && jtp->shortcut &&
  294.         !strcmp(buf, jtp->shortcut)) {
  295.         _statusline(EDIT_CURRENT_SHORTCUT);
  296.         } else if ((jump_buffer && ShortcutTotal == 2) ||
  297.                (!jump_buffer && ShortcutTotal == 1)) {
  298.         _statusline(EDIT_THE_PREV_SHORTCUT);
  299.         } else {
  300.         _statusline(EDIT_A_PREV_SHORTCUT);
  301.         }
  302.         if ((ch=LYgetstr(buf, VISIBLE,
  303.                  sizeof(buf), recall)) < 0) {
  304.         /*
  305.          * User cancelled the jump via ^G.
  306.          */
  307.         _statusline(CANCELLED);
  308.         sleep(InfoSecs);
  309.         return NULL;
  310.         }
  311.         goto check_recall;
  312.     }
  313.     } else if (recall && ch == DNARROW) {
  314.     if (FirstShortcutRecall) {
  315.         /*
  316.          * Use the first Shortcut in the list. - FM
  317.          */
  318.         FirstShortcutRecall = FALSE;
  319.         ShortcutNum = ShortcutTotal - 1;
  320.     } else {
  321.         /*
  322.          * Advance to the next Shortcut in the list. - FM
  323.          */
  324.         ShortcutNum--;
  325.     }
  326.     if (ShortcutNum < 0)
  327.         /*
  328.          * Roll around to the first Shortcut in the list. - FM
  329.          */
  330.         ShortcutNum = ShortcutTotal - 1;
  331.     if ((cp=(char *)HTList_objectAt(jtp->history,
  332.                     ShortcutNum)) != NULL) {
  333.         strcpy(buf, cp);
  334.         if (jump_buffer && jtp->shortcut &&
  335.         !strcmp(buf, jtp->shortcut)) {
  336.         _statusline(EDIT_CURRENT_SHORTCUT);
  337.         } else if ((jump_buffer && ShortcutTotal == 2) ||
  338.                (!jump_buffer && ShortcutTotal == 1)) {
  339.         _statusline(EDIT_THE_PREV_SHORTCUT);
  340.         } else {
  341.         _statusline(EDIT_THE_PREV_SHORTCUT);
  342.         }
  343.         if ((ch=LYgetstr(buf, VISIBLE,
  344.                  sizeof(buf), recall)) < 0) {
  345.         /*
  346.          * User cancelled the jump via ^G.
  347.          */
  348.         _statusline(CANCELLED);
  349.         sleep(InfoSecs);
  350.         return NULL;
  351.         }
  352.         goto check_recall;
  353.     }
  354.     }
  355.  
  356.     seeking.key = bp;
  357.     found = (JumpDatum *)bsearch((char *)&seeking, (char *)jtp->table,
  358.                  jtp->nel, sizeof(JumpDatum), LYCompare);
  359.     if (!found) {
  360.     user_message("Unknown target '%s'", buf);
  361.     sleep(AlertSecs);
  362.     }
  363.  
  364.     StrAllocCopy(jtp->shortcut, bp);
  365.     LYAddJumpShortcut(jtp->history, jtp->shortcut);
  366.     return found ? found->url : NULL;
  367. }
  368.  
  369. PRIVATE unsigned LYRead_Jumpfile ARGS1(struct JumpTable *,jtp)
  370. {
  371.     struct stat st;
  372.     unsigned int nel;
  373.     char *mp;
  374.     int fd;
  375. #ifdef VMS
  376.     FILE *fp;
  377.     BOOL IsStream_LF = TRUE;
  378. #endif /* VMS */
  379.     char *cp;
  380.     unsigned i;
  381.  
  382.     if (jtp->file == NULL || *(jtp->file) == '\0')
  383.     return 0;
  384.     if (stat(jtp->file, &st) < 0) {
  385.     HTAlert(CANNOT_LOCATE_JUMP_FILE);
  386.     return 0;
  387.     }
  388.  
  389.     /* allocate storage to read entire file */
  390.     if ((mp=(char *)calloc(1, st.st_size + 1)) == NULL) {
  391.     HTAlert(OUTOF_MEM_FOR_JUMP_FILE);
  392.     return 0;
  393.     }
  394.  
  395. #ifdef VMS
  396.     if (st.st_fab_rfm != (char)FAB$C_STMLF) {
  397.     /** It's a record-oriented file. **/
  398.     IsStream_LF = FALSE;
  399.     if ((fp = fopen(jtp->file, "r", "mbc=32")) == NULL) {
  400.         HTAlert(CANNOT_OPEN_JUMP_FILE);
  401.         FREE(mp);
  402.         return 0;
  403.     }
  404.     } else
  405.     if ((fd=open(jtp->file, O_RDONLY, "mbc=32")) < 0) {
  406. #else
  407.     if ((fd=open(jtp->file, O_RDONLY)) < 0) {
  408. #endif /* VMS */
  409.     HTAlert(CANNOT_OPEN_JUMP_FILE);
  410.     FREE(mp);
  411.     return 0;
  412.     }
  413.  
  414. #ifdef VMS
  415.     if (IsStream_LF) {
  416.     /** Handle as a stream. **/
  417. #endif /* VMS */
  418.     if (read(fd, mp, st.st_size) < st.st_size) {
  419.     HTAlert(ERROR_READING_JUMP_FILE);
  420.     FREE(mp);
  421.     return 0;
  422.     }
  423.     mp[st.st_size] = '\0';
  424.     close(fd);
  425. #ifdef VMS
  426.     } else {
  427.     /** Handle as a series of records. **/
  428.     if(fgets(mp, 1024, fp) == NULL) {
  429.     HTAlert(ERROR_READING_JUMP_FILE);
  430.     FREE(mp);
  431.     return 0;
  432.     } else
  433.     while(fgets(mp+strlen(mp), 1024, fp) != NULL) ;
  434.     fclose(fp);
  435.     }
  436. #endif /* VMS */
  437.  
  438.     /* quick scan for approximate number of entries */
  439.     nel = 0;
  440.     cp = mp;
  441.     while((cp = strchr(cp, '\n')) != NULL) {
  442.     nel++;
  443.     cp++;
  444.     }
  445.  
  446.     jtp->table = (JumpDatum *)malloc(nel * sizeof(JumpDatum));
  447.     if (jtp->table == NULL) {
  448.     HTAlert(OUTOF_MEM_FOR_JUMP_TABLE);
  449.     FREE(mp);
  450.     return 0;
  451.     }
  452.  
  453.     cp = jtp->mp = mp;
  454.     for (i = 0; i < nel; ) {
  455.     if (strncmp(cp, "<!--", 4) == 0 || strncmp(cp, "<dl>", 4) == 0) {
  456.         cp = strchr(cp, '\n');
  457.         if (cp == NULL)
  458.         break;
  459.         cp++;
  460.         continue;
  461.     }
  462.     cp = LYstrstr(cp, "<dt>");
  463.     if (cp == NULL)
  464.         break;
  465.     cp += 4;
  466.     jtp->table[i].key = cp;
  467.     cp = LYstrstr(cp, "<dd>");
  468.     if (cp == NULL)
  469.         break;
  470.     *cp = '\0';
  471.     cp += 4;
  472.     cp = LYstrstr(cp, "href=\"");
  473.     if (cp == NULL)
  474.         break;
  475.     cp += 6;
  476.     jtp->table[i].url = cp;
  477.     cp = strchr(cp, '"');
  478.     if (cp == NULL)
  479.         break;
  480.     *cp = '\0';
  481.     cp++;
  482.     cp = strchr(cp, '\n');
  483.     if (cp == NULL)
  484.         break;
  485.     cp++;
  486.     i++;
  487.     if (!cp)
  488.         break;
  489.     }
  490.  
  491.     return i;
  492. }
  493.  
  494. PRIVATE int LYCompare ARGS2 (CONST void *, e1, CONST void *, e2)
  495. {
  496.     return strcasecomp(((CONST JumpDatum *)e1)->key, ((CONST JumpDatum *)e2)->key);
  497. }
  498.