home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume22 / nn6.4 / part13 / folder.c < prev   
Encoding:
C/C++ Source or Header  |  1990-06-07  |  8.7 KB  |  460 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Folder handling
  5.  */
  6.  
  7. /*#include <errno.h>*/
  8. #include "config.h"
  9. #include "articles.h"
  10. #include "news.h"
  11. #include "term.h"
  12. #include "menu.h"
  13.  
  14. export int  dont_sort_folders = 0;
  15. export char *folder_directory  = NULL;
  16.  
  17. /*
  18.  *     file name completion and expansion
  19.  *
  20.  *    expand_mode bits:
  21.  *        1:    expand path names
  22.  *        2:    don't expand $N
  23.  *        4:    don't expand any $?  (but $(...) is expanded)
  24.  *        8:    don't complain about ~... (shell will do that)
  25.  */
  26.  
  27.  
  28. expand_file_name(dest, src, expand_mode)
  29. char *dest, *src;
  30. int expand_mode;
  31. {
  32.     register char *cp, *dp, c;
  33.     int parse, remap;
  34.     char *cur_grp, *cur_art;
  35.     import char *home_directory;
  36.  
  37.     cur_grp = current_group ? current_group->group_name : NULL;
  38.     cur_art = (group_file_name && *group_file_name) ? group_path_name : NULL;
  39.  
  40.     for (dp = dest, parse = 1; c = *src; src++) {
  41.  
  42.     if (parse) {
  43.  
  44.         if ((expand_mode & 1) && c == '+') {
  45.         if (folder_directory == NULL) {
  46.             if (!(cp = getenv("FOLDER")))
  47.             cp = FOLDER_DIRECTORY;
  48.             folder_directory = home_relative(cp);
  49.         }
  50.  
  51.         cp = folder_directory;
  52.         goto cp_str;
  53.         }
  54.  
  55.         if ((expand_mode & 1) && c == '~') {
  56.         if (src[1] != '/') {
  57.             if (expand_mode & 8) goto copy;
  58.             msg("Can't handle ~user expansion (yet)");
  59.             return 0;
  60.         }
  61.  
  62.         cp = home_directory;
  63.  
  64.          cp_str:
  65.         while (*cp) *dp++ = *cp++;
  66.         if (dp[-1] != '/') *dp++ = '/';
  67.         goto no_parse;
  68.         }
  69.  
  70.         if ((expand_mode & 4) == 0 &&
  71.         cur_art && c == '%' && (src[1] == ' ' || src[1] == NUL)) {
  72.         cp = cur_art;
  73.         while (*cp) *dp++ = *cp++;
  74.         goto no_parse;
  75.         }
  76.  
  77.     }
  78.  
  79.     if (c == '$' && src[1] == '(') {
  80.         char envar[64];
  81.         for (src += 2, cp = envar; (c = *src) != NUL && c != ')'; src++)
  82.         *cp++ = c;
  83.         *cp = NUL;
  84.         if (cp != envar) {
  85.         if ((cp = getenv(envar)) != NULL)
  86.             while (*cp) *dp++ = *cp++;
  87.         else {
  88.             msg("Environment variable $(%d) not set", envar);
  89.             return 0;
  90.         }
  91.         }
  92.         goto no_parse;
  93.     }
  94.  
  95.     if ((expand_mode & 4) == 0 && c == '$' && !isalnum(src[2])) {
  96.         remap = 0;
  97.         cp = NULL;
  98.  
  99.         switch (src[1]) {
  100.          case 'A':
  101.         cp = cur_art;
  102.         break;
  103.          case 'F':
  104.         cp = cur_grp;
  105.         remap = 1;
  106.         break;
  107.          case 'G':
  108.         cp = cur_grp;
  109.         break;
  110.          case 'L':
  111.         if (cp = strrchr(cur_grp, '.'))
  112.             cp++;
  113.         else
  114.             cp = cur_grp;
  115.         break;
  116.          case 'N':
  117.         if (expand_mode & 2) goto copy;
  118.         if (cur_art) cp = group_file_name;
  119.         if (cp == NULL) goto copy;
  120.         break;
  121.          default:
  122.         goto copy;
  123.         }
  124.         src++;
  125.  
  126.         if (!cp) {
  127.         msg("$%c not defined on this level", c);
  128.         return 0;
  129.         }
  130.  
  131.         while (*cp)
  132.         if (remap && *cp == '.')
  133.             cp++, *dp++ = '/';
  134.         else
  135.             *dp++ = *cp++;
  136.         goto no_parse;
  137.     }
  138.  
  139.     if (c == '/')
  140.         if (dp != dest && dp[-1] == '/') goto no_parse;
  141.  
  142.      copy:
  143.     *dp++ = c;
  144.     parse = isspace(c);
  145.     continue;
  146.  
  147.      no_parse:
  148.         parse = 0;
  149.     }
  150.  
  151.     *dp = NUL;
  152.  
  153.     return 1;
  154. }
  155.  
  156.  
  157. file_completion(path, index)
  158. char *path;
  159. int index;
  160. {
  161.     static dir_in_use = 0;
  162.     static char *head, *tail = NULL;
  163.     static int  tail_offset;
  164.  
  165.     char nbuf[FILENAME], buffer[FILENAME];
  166.     char *dir, *base;
  167.  
  168.     if (path) {
  169.     if (dir_in_use) {
  170.         close_directory();
  171.         dir_in_use = 0;
  172.     }
  173.  
  174.     if (index < 0) return 0;
  175.  
  176.     head = path;
  177.     tail = path + index;
  178.     }
  179.  
  180.     if (!dir_in_use) {
  181.     path = head;
  182.     *tail = NUL;
  183.  
  184.     if (*path == '|') return -1;    /* no completion for pipes */
  185.  
  186.     if (*path == '+' || *path == '~') {
  187.         if (!expand_file_name(nbuf, path, 1))
  188.         return 0;    /* no completions */
  189.     } else
  190.         strcpy(nbuf, path);
  191.  
  192.     if (base = strrchr(nbuf, '/')) {
  193.         if (base == nbuf) {
  194.         dir = "/";
  195.         base++;
  196.         } else {
  197.         *base++ = NUL;
  198.         dir = nbuf;
  199.         }
  200.     } else {
  201.         base = nbuf;
  202.         dir = ".";
  203.     }
  204.  
  205.     tail_offset = strlen(base);
  206.  
  207.     dir_in_use = list_directory(dir, base);
  208.  
  209.     return dir_in_use;
  210.     }
  211.  
  212.     if (index)
  213.     return compl_help_directory();
  214.  
  215.     if (!next_directory(buffer, 1)) return 0;
  216.  
  217.     strcpy(tail, buffer+tail_offset);
  218.  
  219.     return 1;
  220. }
  221.  
  222.  
  223. static int cancel_count;
  224.  
  225. fcancel(ah)
  226. article_header *ah;
  227. {
  228.     if (ah->attr == A_CANCEL) {
  229.     cancel_count--;
  230.     ah->flag = 0;
  231.     } else {
  232.     cancel_count++;
  233.     ah->attr = A_CANCEL;
  234.     }
  235. }
  236.  
  237. static folder_header()
  238. {
  239.     so_printxy(0, 0, "Folder: %s", current_group->group_name);
  240.  
  241.     return 1;    /* number of header lines */
  242. }
  243.  
  244. folder_menu(path)
  245. char *path;
  246. {
  247.     FILE             *folder;
  248.     register article_header    *ah;
  249.     news_header_buffer         dgbuf;
  250.     char             buffer[256];
  251.     int                more, length, re, menu_cmd, was_raw;
  252.     memory_marker        mem_marker;
  253.     group_header         fake_group;
  254.     int                cc_save;
  255.     extern time_stamp pack_date();
  256.  
  257.     fake_group.group_name = path;
  258.     fake_group.group_flag = G_FOLDER | G_FAKED;
  259.     fake_group.master_flag = 0;
  260.     fake_group.save_file = NULL;
  261.     current_group = NULL;
  262.     init_group(&fake_group);
  263.  
  264.     folder = open_file(path, OPEN_READ);
  265.     if (folder == NULL) {
  266.     msg("%s not found", path);
  267.     return ME_NO_REDRAW;
  268.     }
  269.  
  270.     was_raw = no_raw();
  271.     s_keyboard = 0;
  272.  
  273.     printf("\rReading: %-.65s", path);
  274.     clrline();
  275.  
  276.     current_group = &fake_group;
  277.  
  278.     mark_memory(&mem_marker);
  279.  
  280.     ah = alloc_art();
  281.  
  282.     more = 1;
  283.     while (more && (more = get_digest_article(folder, dgbuf)) >= 0) {
  284.     if (s_keyboard) break;
  285.  
  286.     ah->a_number = 0;
  287.     ah->flag = A_FOLDER;
  288.     ah->attr = 0;
  289.  
  290.     ah->lines = digest.dg_lines;
  291.  
  292.     ah->hpos = digest.dg_hpos;
  293.     ah->fpos = digest.dg_fpos;
  294.     ah->lpos = digest.dg_lpos;
  295.  
  296.     if (digest.dg_from) {
  297.         length = pack_name(buffer, digest.dg_from, NAME_LENGTH);
  298.         ah->sender = alloc_str(length);
  299.         strcpy(ah->sender, buffer);
  300.         ah->name_length = length;
  301.     } else {
  302.         ah->sender = "";
  303.         ah->name_length = 0;
  304.     }
  305.  
  306.     if (digest.dg_subj) {
  307.         length = pack_subject(buffer, digest.dg_subj, &re, 255);
  308.         ah->replies = re;
  309.         ah->subject = alloc_str(length);
  310.         strcpy(ah->subject, buffer);
  311.         ah->subj_length = length;
  312.     } else {
  313.         ah->replies = 0;
  314.         ah->subject = "";
  315.         ah->subj_length = 0;
  316.     }
  317.  
  318.     ah->t_stamp = digest.dg_date ? pack_date(digest.dg_date) : 0;
  319.  
  320.     add_article(ah);
  321.     ah = alloc_art();
  322.     }
  323.  
  324.     fclose(folder);
  325.  
  326.     if (was_raw) raw();
  327.  
  328.     if (s_keyboard) {
  329.     menu_cmd = ME_NO_REDRAW;
  330.     } else
  331.     if (n_articles == 0) {
  332.     msg("Not a folder (no article header)");
  333.     menu_cmd = ME_NO_REDRAW;
  334.     } else {
  335.     strcpy(buffer, path);
  336.     fake_group.group_name = buffer;    /* save for later use */
  337.  
  338.     if (n_articles > 1) {
  339.         clrdisp();
  340.         prompt_line = 2;
  341.         if (!dont_sort_folders) sort_articles(-1);
  342.     }
  343.  
  344.     cc_save = cancel_count;
  345.     cancel_count = 0;
  346.  
  347.      reenter_menu:
  348.     menu_cmd = menu(folder_header);
  349.  
  350.     if (cancel_count) {
  351.         clrdisp();
  352.         printf("Folder: %s\nFile:   %s\n\n", buffer, group_path_name);
  353.         if (cancel_count == n_articles)
  354.         printf("Cancel all articles and remove folder? ");
  355.         else
  356.         printf("Remove %d article%s from folder? ",
  357.                cancel_count, plural((long)cancel_count));
  358.         fl;
  359.  
  360.         switch (yes(1)) {
  361.          case 1:
  362.         printf("\n\n");
  363.         if (cancel_count == n_articles) {
  364.             if (unlink(group_path_name) < 0) {
  365.             printf("Could not unlink %s\n", group_path_name);
  366.             sleep(3);
  367.             }
  368.         } else
  369.             rewrite_folder();
  370.         break;
  371.          case 0:
  372.         break;
  373.          default:
  374.         goto reenter_menu;
  375.         }
  376.     }
  377.     cancel_count = cc_save;
  378.     }
  379.  
  380.     release_memory(&mem_marker);
  381.  
  382.     return menu_cmd;
  383. }
  384.  
  385.  
  386. rewrite_folder()
  387. {
  388.     register FILE *src, *dst;
  389.     char oldfile[FILENAME], *sp;
  390.     register int c;
  391.     register long cnt;
  392.     register article_header *ah, **ahp;
  393.     register article_number n;
  394.  
  395.     if ((src = fopen(group_path_name, "r")) == NULL) {
  396.     msg("Cannot open %s", group_path_name);
  397.     return;
  398.     }
  399.  
  400.     strcpy(oldfile, group_path_name);
  401.     sp = strrchr(oldfile, '/');
  402.     strcpy((sp == NULL ? oldfile : sp+1), "~OLD~FOLDER~");
  403.  
  404.     unlink(oldfile);
  405.     if (link(group_path_name, oldfile) < 0) goto move_error;
  406.     if (unlink(group_path_name) < 0) {
  407.     if (unlink(oldfile) == 0) goto move_error;
  408.     printf("\n\n%s was linked to %s --- cannot proceed\n",
  409.            group_path_name, oldfile);
  410.     sleep(5);
  411.     return;
  412.     }
  413.  
  414.     if ((dst = fopen(group_path_name, "w")) == NULL) {
  415.     fclose(src);
  416.     goto move_back;
  417.     }
  418.  
  419.     sort_articles(0);
  420.  
  421.     printf("Compressing folder..."); fl;
  422.  
  423.     for (ahp = articles, n = n_articles; --n >= 0; ahp++) {
  424.     ah = *ahp;
  425.     if (ah->attr == A_CANCEL) continue;
  426.     fseek(src, ah->hpos, 0);
  427.     cnt = ah->lpos - ah->hpos;
  428.     while (--cnt >= 0) {
  429.         if ((c = getc(src)) == EOF) break;
  430.         putc(c, dst);
  431.     }
  432.     putc(NL, dst);
  433.     }
  434.     fclose(src);
  435.     if (ferror(dst)) {
  436.     fclose(dst);
  437.     goto move_back;
  438.     }
  439.     return;
  440.  
  441. move_back:
  442.     if (link(oldfile, group_path_name) == 0) {
  443.     unlink(oldfile);
  444.     printf("Cannot create new file -- Folder restored\n");
  445.     sleep(2);
  446.     } else {
  447.     printf("Cannot create new file\n\nFolder saved in %s\n",
  448.            oldfile);
  449.     sleep(10);
  450.     }
  451.     return;
  452.  
  453. move_error:
  454.     fclose(src);
  455.     printf("\n\nCannot move folder %s to %s\n",
  456.        group_path_name, oldfile);
  457.     sleep(3);
  458.     return;
  459. }
  460.