home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume18 / mush / part19 < prev    next >
Internet Message Format  |  1991-04-22  |  51KB

  1. From: argv@zipcode.com (Dan Heller)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i076:  mush - Mail User's Shell, Part19/22
  4. Message-ID: <1991Apr22.153718.29937@sparky.IMD.Sterling.COM>
  5. Date: 22 Apr 91 15:37:18 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 088477df 409e87ec 080f5de9 59ebbf07
  8.  
  9. Submitted-by: Dan Heller <argv@zipcode.com>
  10. Posting-number: Volume 18, Issue 76
  11. Archive-name: mush/part19
  12. Supersedes: mush: Volume 12, Issue 28-47
  13.  
  14. #!/bin/sh
  15. # do not concatenate these parts, unpack them in order with /bin/sh
  16. # file options.c continued
  17. #
  18. if test ! -r _shar_seq_.tmp; then
  19.     echo 'Please unpack part 1 first!'
  20.     exit 1
  21. fi
  22. (read Scheck
  23.  if test "$Scheck" != 19; then
  24.     echo Please unpack part "$Scheck" next!
  25.     exit 1
  26.  else
  27.     exit 0
  28.  fi
  29. ) < _shar_seq_.tmp || exit 1
  30. if test ! -f _shar_wnt_.tmp; then
  31.     echo 'x - still skipping options.c'
  32. else
  33. echo 'x - continuing file options.c'
  34. sed 's/^X//' << 'SHAR_EOF' >> 'options.c' &&
  35. {
  36. X    int i;
  37. X
  38. X    Debug("%s --> ", *argp);
  39. X    for (i = 0; word_flags[i][0]; i++) {
  40. X    int len = strlen(word_flags[i][0]);
  41. X    if (! strncmp(*argp, word_flags[i][0], len)) {
  42. X        char buf[BUFSIZ], *p = buf;
  43. X        p += Strcpy(buf, word_flags[i][1]);
  44. X        (void) strcpy(p, *argp + len);
  45. X        (void) strcpy(*argp, buf);
  46. X    }
  47. X    }
  48. X    Debug("%s\n", *argp);
  49. }
  50. X
  51. /*
  52. X * preparse the command line to determine whether or not we're going
  53. X * to bail out after checking that the user has no mail.  Also, check
  54. X * to see if we're going to run a tool because it must be built first.
  55. X */
  56. preparse_opts(argcp, argv)
  57. register int *argcp;    /* Pointer to argument count */
  58. register char **argv;    /* Argument vector */
  59. {
  60. X    int n = FALSE;
  61. X    char **args;
  62. X
  63. #ifdef SUNTOOL
  64. X    /* Note: we are assigning a boolean result to n and istool here */
  65. X    if (n = istool = (strlen(prog_name) > 3 &&
  66. X         (!strcmp(prog_name+strlen(prog_name)-4, "tool") ||
  67. X          !strcmp(prog_name+strlen(prog_name)-4, "view")))) {
  68. X    turnon(glob_flags, DO_SHELL);
  69. X    parse_tool_opts(argcp, argv);
  70. X    }
  71. #endif /* SUNTOOL */
  72. X
  73. X    if (!istool && *argcp > 1) {
  74. X    for (args = argv+1; *args && args[0][0] == '-'; args++) {
  75. X        int next = 1;
  76. X        fix_word_flag(&args[0]);
  77. DoNext:
  78. X        switch (args[0][next]) {
  79. #ifdef SUNTOOL
  80. X        case 'T' :
  81. X            if (args[1])
  82. X            args++;
  83. X        case 't' :
  84. X            /* Note: we won't ever get here if started as
  85. X             * "mushtool" or "mushview" because istool is true.
  86. X             */
  87. X            istool = 1;
  88. X            parse_tool_opts(argcp, argv);
  89. X            turnon(glob_flags, DO_SHELL);
  90. X            return TRUE;
  91. X            /* break; */
  92. #endif /* SUNTOOL */
  93. X        case 'S' :
  94. X            turnon(glob_flags, DO_SHELL);
  95. X            n = TRUE;
  96. X            break;
  97. X        case 'f' :
  98. X        case 'F' :
  99. X        case 'h' :
  100. X        case 'm' :
  101. X        case 'u' :
  102. X            n = TRUE;
  103. X        case 'b' :
  104. X        case 'c' :
  105. X        case 'I' :
  106. X        case 's' :
  107. X            if (args[1]) {
  108. X            args++;
  109. X            next = 0;
  110. X            }
  111. X            break;
  112. X        case 'H' :
  113. X            if (args[0][next+1] == ':')
  114. X            next = 0;
  115. X            break;
  116. X        case '\0':
  117. X            next = 0;
  118. X        default : ;
  119. X        }
  120. X        if (next) {
  121. X        ++next;
  122. X        goto DoNext;
  123. X        }
  124. X    }
  125. X    if (*args) {  /* unused args indicates sending mail to someone */
  126. X        n = TRUE;
  127. X        if (!istool)
  128. X        turnon(glob_flags, IS_SENDING);
  129. X    }
  130. X    }
  131. X
  132. X    return n;
  133. }
  134. X
  135. static char *usage_str =
  136. #ifdef SUNTOOL
  137. X    "usage: %s [-t] [-C] [-i] [-f [folder] ] [-v] [-S] [-s subject] [users]\n";
  138. #else
  139. #ifdef CURSES
  140. X    "usage: %s [-C] [-i] [-f [folder] ] [-v] [-S] [-s subject] [user list]\n";
  141. #else
  142. X    "usage: %s [-i] [-f [folder] ] [-v] [-S] [-s subject] [user list]\n";
  143. #endif /* CURSES */
  144. #endif /* SUNTOOL */
  145. X
  146. parse_options(argvp, flags)
  147. register char ***argvp;
  148. struct mush_flags *flags;
  149. {
  150. X    char buf[256];
  151. X
  152. X    bzero((char *) flags, sizeof (struct mush_flags));
  153. X    flags->source_rc = TRUE;
  154. X    flags->folder = "";
  155. X
  156. X    for (++(*argvp); **argvp && ***argvp == '-'; (*argvp)++) {
  157. X    int look_again;
  158. DoLookAgain:
  159. X    look_again = TRUE;
  160. X    switch ((*argvp)[0][1]) {
  161. X        case 'e':
  162. X        /*
  163. X         * don't set tty modes -- e.g. echo and cbreak modes aren't
  164. X         * changed.
  165. X         */
  166. X        turnon(glob_flags, ECHO_FLAG);
  167. #ifdef CURSES
  168. X        when 'C':
  169. X        /* don't init curses -- don't even set iscurses.   */
  170. X        if (istool) {
  171. X            puts("-C: You are already running in tool mode");
  172. X            turnoff(glob_flags, PRE_CURSES);
  173. X        } else if (hdrs_only)
  174. X            puts("headers only: ignoring -C flag");
  175. X        else
  176. X            turnon(glob_flags, PRE_CURSES);
  177. #endif /* CURSES */
  178. X        when 'F':
  179. X        flags->src_n_exit = ((*argvp)[0][2] == '!');
  180. X        if (!(flags->src_file = *++(*argvp)))
  181. X            puts("specify filename to source"), exit(1);
  182. X        look_again = FALSE;
  183. X        /* fall thru! */
  184. X        case 'N':
  185. X        (void) strcat(flags->f_flags, "-N ");
  186. X        when 'r':
  187. X        (void) strcat(flags->f_flags, "-r "); /* folder() argument */
  188. X        when 'H':
  189. X        if (istool) {
  190. X            puts("running in tool-mode; -H option ignored.");
  191. X            break;
  192. X        }
  193. X        turnoff(glob_flags, PRE_CURSES);
  194. X        if (*(hdrs_only = (*(*argvp))+2) != ':')
  195. X            hdrs_only = ":a";
  196. X        else
  197. X            look_again = FALSE;
  198. X        /* read only cuz no updates */
  199. X        (void) strcat(flags->f_flags, "-N -r ");
  200. X        when 'i':
  201. X        /* force interactive even if !isatty(0) */
  202. X        turnoff(glob_flags, REDIRECT);
  203. X        when 'u': /* specify a user's mailbox */
  204. X        if (*(flags->folder))
  205. X            puts("You can't specify more than one mailbox"), exit(1);
  206. #ifdef HOMEMAIL
  207. X        {
  208. X            char *p;
  209. X            int isdir = 1;
  210. X            (void) sprintf(buf, "%%%s",
  211. X                (*argvp)[1] ? (*argvp)[1] : "root");
  212. X            if ((p = getpath(buf, &isdir)) && !isdir)
  213. X            strdup(flags->folder, p);
  214. X            else if (isdir < 0)
  215. X            puts(p), exit(1);
  216. X            else if (isdir)
  217. X            (void) printf("\"%s\" is a directory\n", p), exit(1);
  218. X        }
  219. #else /* HOMEMAIL */
  220. X        strdup(flags->folder, sprintf(buf, "%s/%s",
  221. X                   MAILDIR, ((*argvp)[1])? (*argvp)[1] : "root"));
  222. #endif /* HOMEMAIL */
  223. X        if ((*argvp)[1])
  224. X            ++(*argvp);
  225. X        look_again = FALSE;
  226. X        when 'h':
  227. X        if (istool)
  228. X            puts("bad option when run as a tool"), exit(1);
  229. X        if ((*argvp)[1])
  230. X            flags->draft = *++(*argvp);
  231. X        else
  232. X            (void) printf("-h: missing file name.\n"), exit(1);
  233. X        look_again = FALSE;
  234. X        turnon(glob_flags, IS_SENDING);
  235. X        when 'U':
  236. X        if (istool)
  237. X            puts("bad option when run as a tool"), exit(1);
  238. X        turnon(flags->flg, SEND_NOW);
  239. X        if ((*argvp)[0][2] == '!') {
  240. X            turnon(flags->flg, NO_SIGN);
  241. X            ++(**argvp);
  242. X        }
  243. X        when 'm':
  244. X        if ((*argvp)[1])
  245. X            strdup(spoolfile, *++(*argvp));
  246. X        else
  247. X            (void) printf("-m: missing mailbox name.\n"), exit(1);
  248. X        look_again = FALSE;
  249. X        when 'f':
  250. X        if (*(flags->folder))
  251. X            puts("You can't specify more than one mailbox"), exit(1);
  252. X        if ((*argvp)[1]) {
  253. X            strdup(flags->folder, *++(*argvp));
  254. X            look_again = FALSE;
  255. X        } else
  256. X            strdup(flags->folder, "&");
  257. X        when 's':
  258. X        if (istool)
  259. X            puts("bad option when run as a tool"), exit(1);
  260. X        else if ((*argvp)[1])
  261. X            flags->Subj = *++(*argvp);
  262. X        else
  263. X            puts("-s \"subject\""), exit(1);
  264. X        look_again = FALSE;
  265. X        when 'b':
  266. X        if (istool)
  267. X            puts("-b: bad option when run as a tool"), exit(1);
  268. X        else if ((*argvp)[1])
  269. X            flags->Bcc = *++(*argvp);
  270. X        else
  271. X            puts("-b \"bcc list\""), exit(1);
  272. X        look_again = FALSE;
  273. X        when 'c':
  274. X        if (istool)
  275. X            puts("-c: bad option when run as a tool"), exit(1);
  276. X        else if ((*argvp)[1])
  277. X            flags->Cc = *++(*argvp);
  278. X        else
  279. X            puts("-c \"cc list\""), exit(1);
  280. X        look_again = FALSE;
  281. X        break;
  282. #ifdef VERBOSE_ARG
  283. X        case 'v':
  284. X        if (istool)
  285. X            puts("bad option when run as a tool"), exit(1);
  286. X        turnon(flags->flg, VERBOSE);
  287. X        break;
  288. #endif /* VERBOSE_ARG */
  289. #ifdef SUNTOOL
  290. X        case 'T':
  291. X        if ((time_out = atoi(*(*argvp))) <= 29)
  292. X            time_out = 30;
  293. X        look_again = FALSE;
  294. X        /* -T implies -t */
  295. X        case 't': istool = 1;
  296. #endif /* SUNTOOL */
  297. X        case 'S': turnon(glob_flags, DO_SHELL);
  298. X        when 'n':
  299. X        if ((*argvp)[0][2] == '!') {
  300. X            ++(**argvp);
  301. X            flags->source_rc = -1;    /* No init files sourced */
  302. X        } else
  303. X            flags->source_rc = 0;    /* Only ~/.mushrc sourced */
  304. X        when 'I':
  305. X        if ((*argvp)[0][2] == '!' && flags->source_rc > 0)
  306. X            flags->source_rc = 0;    /* Only ~/.mushrc sourced */
  307. X        if (!(flags->init_file = *++(*argvp)))
  308. X            puts("specify filename for init"), exit(1);
  309. X        look_again = FALSE;
  310. X        when 'd': debug = 1;
  311. X        when '\0' : look_again = FALSE;
  312. X        otherwise:
  313. X        print("%s: unknown option: `%c'\n", prog_name,
  314. X            (*argvp)[0][1]? (*argvp)[0][1] : '-');
  315. X        print(usage_str, prog_name);
  316. X    }
  317. X    if (look_again && ++(**argvp) != '\0')
  318. X        goto DoLookAgain;
  319. X    }
  320. X
  321. X    if (ison(flags->flg, SEND_NOW) && !flags->draft) {
  322. X    print("You must specify a draft file to autosend\n");
  323. X    exit(1);
  324. X    }
  325. }
  326. SHAR_EOF
  327. echo 'File options.c is complete' &&
  328. chmod 0644 options.c ||
  329. echo 'restore of options.c failed'
  330. Wc_c="`wc -c < 'options.c'`"
  331. test 8816 -eq "$Wc_c" ||
  332.     echo 'options.c: original size 8816, current size' "$Wc_c"
  333. rm -f _shar_wnt_.tmp
  334. fi
  335. # ============= options.h ==============
  336. if test -f 'options.h' -a X"$1" != X"-c"; then
  337.     echo 'x - skipping options.h (File already exists)'
  338.     rm -f _shar_wnt_.tmp
  339. else
  340. > _shar_wnt_.tmp
  341. echo 'x - extracting options.h (Text)'
  342. sed 's/^X//' << 'SHAR_EOF' > 'options.h' &&
  343. /* @(#)options.h    (c) copyright 10/10/88 (Dan Heller, Bart Schaefer) */
  344. X
  345. /* Must #include mush.h before #including this file */
  346. X
  347. /* Structure to hold assorted information collected from command line flags.  
  348. X *  Other information is held in the following global variables:
  349. X *    cmd_help    General help file, specified by -1
  350. X *    debug        Debugging mode, toggled by -d
  351. X *    glob_flags    Bits set by -C, -e, -i, -S, -t and many commands
  352. X *    hdrs_only    Show headers and exit, specified by -H
  353. X *    iscurses    Curses mode, specified by -C or "curses" command
  354. X *    istool        Tool mode, specified by -t or -T
  355. X *    mailfile    File specified by -u or -f or "folder" command
  356. X *    prog_name    Name under which mush is running
  357. X *    time_out    Tool mode timeout, specified by -T
  358. X *    tool_help    Tool mode help file, specified by -2
  359. X */
  360. X
  361. struct mush_flags {
  362. X    u_long flg;        /* Set by -v, -h, -U, vars */
  363. X    char *init_file;    /* Set by -I or -I! */
  364. X    char *src_file;    /* Set by -F */
  365. X    int src_n_exit;    /* Set by -F! */
  366. X    char *folder;    /* Set by -f or -u */
  367. X    char *draft;    /* Set by -h */
  368. X    char f_flags[10];    /* Set by -r, -N, etc.; passed to folder() */
  369. X    char *Subj;        /* Set by -s */
  370. X    char *Cc;        /* Set by -c */
  371. X    char *Bcc;        /* Set by -b */
  372. X    int source_rc;    /* Set by -n */
  373. };
  374. SHAR_EOF
  375. chmod 0644 options.h ||
  376. echo 'restore of options.h failed'
  377. Wc_c="`wc -c < 'options.h'`"
  378. test 1248 -eq "$Wc_c" ||
  379.     echo 'options.h: original size 1248, current size' "$Wc_c"
  380. rm -f _shar_wnt_.tmp
  381. fi
  382. # ============= panels.c ==============
  383. if test -f 'panels.c' -a X"$1" != X"-c"; then
  384.     echo 'x - skipping panels.c (File already exists)'
  385.     rm -f _shar_wnt_.tmp
  386. else
  387. > _shar_wnt_.tmp
  388. echo 'x - extracting panels.c (Text)'
  389. sed 's/^X//' << 'SHAR_EOF' > 'panels.c' &&
  390. /* @(#)panel.c    (c) copyright    10/18/86 (Dan Heller) */
  391. /* @(#)panels.c    (c) copyright    9/29/89 (Dan Heller) */
  392. X
  393. #include "mush.h"
  394. /* mouse symbols */
  395. short dat_mouse_left[] = {
  396. X    0x1FF8, 0x3FFC, 0x336C, 0x336C, 0x336C, 0x336C, 0x336C, 0x336C, 
  397. X    0x3FFC, 0x3FFC, 0x3FFC, 0x3FFC, 0x3FFC, 0x3FC4, 0x3FFC, 0x1FF8
  398. };
  399. X
  400. short dat_mouse_middle[] = {
  401. X    0x1FF8, 0x3FFC, 0x366C, 0x366C, 0x366C, 0x366C, 0x366C, 0x366C, 
  402. X    0x3FFC, 0x3FFC, 0x3FFC, 0x3FFC, 0x3FFC, 0x3FC4, 0x3FFC, 0x1FF8
  403. };
  404. X
  405. short dat_mouse_right[] = {
  406. X    0x1FF8, 0x3FFC, 0x36CC, 0x36CC, 0x36CC, 0x36CC, 0x36CC, 0x36CC, 
  407. X    0x3FFC, 0x3FFC, 0x3FFC, 0x3FFC, 0x3FFC, 0x3FC4, 0x3FFC, 0x1FF8
  408. };
  409. X
  410. mpr_static(mouse_left,      16, 16, 1, dat_mouse_left);
  411. mpr_static(mouse_middle,    16, 16, 1, dat_mouse_middle);
  412. mpr_static(mouse_right,     16, 16, 1, dat_mouse_right);
  413. X
  414. Panel_item
  415. X    folder_item,    /* change folders */
  416. X    folder_text_item,    /* text item for the folder item */
  417. X    file_item,         /* text item for the save item */
  418. X    msg_num_item,    /* text item explicitly states which message to read */
  419. X    read_item,        /* read the current message */
  420. X    save_item,        /* saves messages */
  421. X    sub_hdr_item[6];    /* display items that just sit there and give help */
  422. X
  423. #ifndef NO_WALK_MENUS
  424. Panel
  425. X    folder_panel,
  426. X    save_panel;
  427. Menu      folder_menu;    /* Menu of folders for folder button */
  428. Menu      save_menu;    /* Menu of folders for save button */
  429. Menu      hdr_save_menu;/* Menu of folders for save option in hdr window */
  430. extern Menu msg_menu;    /* header subwindow menu, defined in hdr_sw.c */
  431. walk_menu_event();
  432. #endif /* NO_WALK_MENUS */
  433. X
  434. /* These global panel items for letter composition should eventually go away */
  435. Panel_item
  436. X    edit_item,        /* edit a message */
  437. X    reply_item;        /* reply button -- also called from hdr_sw menu */
  438. X
  439. extern void
  440. X    close_frame(), do_options(), do_compose(), do_send(), do_sort(),
  441. X    do_edit(), delete_mail(), respond_mail(), do_help(), do_lpr(),
  442. X    do_update(), abort_mail(), do_include(), load_from_file(),
  443. X    save_to_file(), tilde_from_menu(), fkey_interposer(), do_mark(),
  444. X    close_compose();
  445. X
  446. extern Panel_setting
  447. X    msg_num_done(), file_dir();
  448. X
  449. Panel
  450. make_hdr_panel(parent, choice_args, button_args)
  451. Frame parent;
  452. char **choice_args, **button_args;
  453. {
  454. X    Panel panel = window_create(parent, PANEL,
  455. X    WIN_CONSUME_KBD_EVENTS,
  456. X        WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, NULL,
  457. X    NULL);
  458. X    (void) notify_interpose_event_func(panel, fkey_interposer, NOTIFY_SAFE);
  459. X
  460. X    (void) panel_create_item(panel, PANEL_CHOICE,
  461. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  462. X    PANEL_LABEL_IMAGE,
  463. X        panel_button_image(panel, "Done", 4, mush_font),
  464. X    PANEL_CHOICE_STRINGS,
  465. X        "Close to Icon", "Quit Tool", "Help", NULL,
  466. X    PANEL_NOTIFY_PROC,         toolquit,
  467. X    NULL);
  468. X
  469. X    (void) panel_create_item(panel, PANEL_CHOICE,
  470. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  471. X    PANEL_LABEL_IMAGE,
  472. X        panel_button_image(panel, "Help", 4, mush_font),
  473. X    PANEL_CHOICE_STRINGS,
  474. X        "About", "Help with \"help\"", "The Mouse", "Windows",
  475. X        "Message headers", "Message lists", "Folders", NULL,
  476. X    PANEL_NOTIFY_PROC,         do_help,
  477. X    NULL);
  478. X
  479. #ifndef NO_WALK_MENUS
  480. X    folder_panel = panel;
  481. X    folder_item = panel_create_item(panel, PANEL_BUTTON,
  482. X    PANEL_ATTRIBUTE_LIST,         button_args,
  483. X    PANEL_LABEL_IMAGE,
  484. X        panel_button_image(panel, "Folder", 6, mush_font),
  485. X    PANEL_NOTIFY_PROC,         do_file_dir,
  486. X    PANEL_EVENT_PROC,        walk_menu_event,
  487. X    NULL);
  488. #else /* NO_WALK_MENUS */
  489. X    folder_item = panel_create_item(panel, PANEL_CHOICE,
  490. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  491. X    PANEL_LABEL_IMAGE,
  492. X        panel_button_image(panel, "Folder", 6, mush_font),
  493. X    PANEL_CHOICE_STRINGS,
  494. X        "System Mailbox", "Main Mailbox", "Last Accessed Folder", NULL,
  495. X    PANEL_NOTIFY_PROC,         do_file_dir,
  496. X    NULL);
  497. X
  498. X    add_folder_to_menu(folder_item, 3);
  499. #endif /* NO_WALK_MENUS */
  500. X
  501. X    folder_text_item = panel_create_item(panel, PANEL_TEXT,
  502. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  503. X    PANEL_LABEL_FONT,         mush_font,
  504. X    PANEL_LABEL_STRING,        "Filename:",
  505. X    PANEL_VALUE_DISPLAY_LENGTH,     28,
  506. X    PANEL_NOTIFY_STRING,         "\n\r\033",
  507. X    PANEL_NOTIFY_PROC,         file_dir,
  508. X    NULL);
  509. X
  510. X    (void) panel_create_item(panel, PANEL_CHOICE,
  511. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  512. X    PANEL_LABEL_IMAGE,
  513. X        panel_button_image(panel, "Update", 6, mush_font),
  514. X    PANEL_CHOICE_STRINGS,         "New Mail", "Help", NULL,
  515. X    PANEL_NOTIFY_PROC,         do_update,
  516. X    NULL);
  517. X
  518. X    (void) panel_create_item(panel, PANEL_CHOICE,
  519. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  520. X    PANEL_LABEL_IMAGE,
  521. X        panel_button_image(panel, "Options", 7, mush_font),
  522. X    PANEL_CHOICE_STRINGS,        "Variables", "Headers", "Aliases", NULL,
  523. X    PANEL_NOTIFY_PROC,         do_options,
  524. X    NULL);
  525. X
  526. X    msg_num_item = panel_create_item(panel, PANEL_TEXT,
  527. X    PANEL_ATTRIBUTE_LIST,        choice_args,
  528. X    PANEL_LABEL_STRING,        "Range:",
  529. X    PANEL_MENU_CHOICE_STRINGS,     "Help", NULL,
  530. X    PANEL_VALUE_DISPLAY_LENGTH,     17,
  531. X    PANEL_VALUE_STORED_LENGTH,     80,
  532. X    PANEL_LABEL_FONT,         mush_font,
  533. X    PANEL_NOTIFY_STRING,         "\n\r",
  534. X    PANEL_NOTIFY_PROC,         msg_num_done,
  535. X    NULL);
  536. X
  537. X    sub_hdr_item[0] = panel_create_item(panel, PANEL_CHOICE,
  538. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  539. X    PANEL_LABEL_IMAGE,            &mouse_left,
  540. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  541. X    PANEL_NOTIFY_PROC,            read_mail,
  542. X    NULL);
  543. X    sub_hdr_item[1] = panel_create_item(panel, PANEL_CHOICE,
  544. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  545. X    PANEL_LABEL_STRING,           "Read ",
  546. X    PANEL_MENU_TITLE_IMAGE,     &mouse_left,
  547. X    PANEL_CHOICE_STRINGS,        "Help", NULL,
  548. X    PANEL_NOTIFY_PROC,            read_mail,
  549. X    NULL);
  550. X    sub_hdr_item[2] = panel_create_item(panel, PANEL_CHOICE,
  551. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  552. X    PANEL_LABEL_IMAGE,            &mouse_middle,
  553. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  554. X    PANEL_NOTIFY_PROC,            delete_mail,
  555. X    NULL);
  556. X    sub_hdr_item[3] = panel_create_item(panel, PANEL_CHOICE,
  557. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  558. X    PANEL_LABEL_STRING,           "Delete ",
  559. X    PANEL_MENU_TITLE_IMAGE,     &mouse_middle,
  560. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  561. X    PANEL_NOTIFY_PROC,            delete_mail,
  562. X    NULL);
  563. X    sub_hdr_item[4] = panel_create_item(panel, PANEL_CHOICE,
  564. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  565. X    PANEL_LABEL_IMAGE,            &mouse_right,
  566. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  567. X    PANEL_NOTIFY_PROC,            read_mail,
  568. X    NULL);
  569. X    sub_hdr_item[5] = panel_create_item(panel, PANEL_CHOICE,
  570. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  571. X    PANEL_LABEL_STRING,           "Menu   ",
  572. X    PANEL_MENU_TITLE_IMAGE,            &mouse_right,
  573. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  574. X    PANEL_NOTIFY_PROC,            read_mail,
  575. X    NULL);
  576. X
  577. X    (void) panel_create_item(panel, PANEL_CHOICE,
  578. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  579. X    PANEL_LABEL_IMAGE,
  580. X        panel_button_image(panel, "Mark", 4, mush_font),
  581. X    PANEL_CHOICE_STRINGS,
  582. X        "Toggle Mark", "Priority A", "Priority B", "Priority C",
  583. X        "Priority D", "Priority E", "Clear Priority", "Help", NULL,
  584. X    PANEL_NOTIFY_PROC,         do_mark,
  585. X    NULL);
  586. X
  587. X    (void) panel_create_item(panel, PANEL_CHOICE,
  588. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  589. X    PANEL_LABEL_IMAGE,
  590. X        panel_button_image(panel, "Printer", 7, mush_font),
  591. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  592. X    PANEL_NOTIFY_PROC,         do_lpr,
  593. X    NULL);
  594. X
  595. X    (void) panel_create_item(panel, PANEL_CHOICE,
  596. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  597. X    PANEL_LABEL_IMAGE,
  598. X        panel_button_image(panel, "Sort", 4, mush_font),
  599. X    PANEL_CHOICE_STRINGS,
  600. X        "By Status", "By Author", "By Size", "By Subject",
  601. X        "By Subject (ignore Re:)", "By Date",
  602. X        "By Priority", "Value of $sort", "Help", NULL,
  603. X    PANEL_NOTIFY_PROC,         do_sort,
  604. X    NULL);
  605. X
  606. X    window_fit_height(panel);
  607. X    return panel;
  608. }
  609. X
  610. Panel
  611. make_main_panel(parent, choice_args, button_args)
  612. Frame parent;
  613. char **choice_args, **button_args;
  614. {
  615. X    /* main panel stuff: */
  616. X    Panel panel = window_create(parent, PANEL,
  617. X    WIN_CONSUME_KBD_EVENTS,
  618. X        WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, NULL,
  619. X    NULL);
  620. X    (void) notify_interpose_event_func(panel, fkey_interposer, NOTIFY_SAFE);
  621. X
  622. X    read_item = panel_create_item(panel, PANEL_CHOICE,
  623. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  624. X    PANEL_LABEL_IMAGE,
  625. X        panel_button_image(panel, "Next", 4, mush_font),
  626. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  627. X    PANEL_NOTIFY_PROC,         read_mail,
  628. X    NULL);
  629. X
  630. X    (void) panel_create_item(panel, PANEL_CHOICE,
  631. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  632. X    PANEL_LABEL_IMAGE,
  633. X        panel_button_image(panel, "Delete", 6, mush_font),
  634. X    PANEL_CHOICE_STRINGS,         "Delete",
  635. X                    "Undelete",
  636. X                    "Help", NULL,
  637. X    PANEL_NOTIFY_PROC,         delete_mail,
  638. X    NULL);
  639. X
  640. #ifndef NO_WALK_MENUS
  641. X    save_panel = panel;
  642. X    save_item = panel_create_item(panel, PANEL_BUTTON,
  643. X    PANEL_ATTRIBUTE_LIST,         button_args,
  644. X    PANEL_LABEL_IMAGE, panel_button_image(panel, "Save", 4, mush_font),
  645. X    PANEL_NOTIFY_PROC,         do_file_dir,
  646. X    PANEL_EVENT_PROC,        walk_menu_event,
  647. X    NULL);
  648. X
  649. X    create_folder_menus();
  650. #else /* NO_WALK_MENUS */
  651. X    {
  652. X    char *mbox = do_set(set_options, "mbox");
  653. X    if (!mbox || !*mbox)
  654. X        mbox = DEF_MBOX;
  655. X    save_item = panel_create_item(panel, PANEL_CHOICE,
  656. X        PANEL_ATTRIBUTE_LIST,     choice_args,
  657. X        PANEL_LABEL_IMAGE, panel_button_image(panel, "Save", 4, mush_font),
  658. X        PANEL_CHOICE_STRINGS,     trim_filename(mbox), NULL,
  659. X        PANEL_NOTIFY_PROC,         do_file_dir,
  660. X        NULL);
  661. X    }
  662. X
  663. X    add_folder_to_menu(save_item, 1);
  664. #endif /* NO_WALK_MENUS */
  665. X
  666. X    file_item = panel_create_item(panel, PANEL_TEXT,
  667. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  668. X    PANEL_LABEL_FONT,         mush_font,
  669. X    PANEL_SHOW_MENU,        TRUE,
  670. X    PANEL_LABEL_STRING,         "Filename:",
  671. X    PANEL_MENU_CHOICE_STRINGS,    "Save message without message header",
  672. X                    NULL,
  673. X    PANEL_VALUE_DISPLAY_LENGTH,     28,
  674. X    PANEL_NOTIFY_STRING,         "\n\r\033",
  675. X    PANEL_NOTIFY_PROC,         file_dir,
  676. X    NULL);
  677. X
  678. X    (void) panel_create_item(panel, PANEL_CHOICE,
  679. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  680. X    PANEL_LABEL_IMAGE,
  681. X        panel_button_image(panel, "Compose", 7, mush_font),
  682. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  683. X    PANEL_NOTIFY_PROC,        do_compose,
  684. X    NULL);
  685. X
  686. X    reply_item = panel_create_item(panel, PANEL_CHOICE,
  687. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  688. X    PANEL_LABEL_IMAGE,
  689. X        panel_button_image(panel, "Reply", 5, mush_font),
  690. X    PANEL_CHOICE_STRINGS,
  691. X        "Sender Only", "Sender Only (include msg)",
  692. X        "All Recipients", "All Recipients (include msg)", "Help", NULL,
  693. X    PANEL_NOTIFY_PROC,         respond_mail,
  694. X    NULL);
  695. X
  696. X    window_fit_height(panel);
  697. X    return panel;
  698. }
  699. X
  700. Panel
  701. make_compose_panel(parent, choice_args, button_args)
  702. Frame parent;
  703. char **choice_args, **button_args;
  704. {
  705. X    Panel panel = window_create(parent, PANEL, NULL);
  706. X    Panel_item filename_item, fortune_item, sign_item, send_item;
  707. X
  708. X    (void) notify_interpose_event_func(panel, fkey_interposer, NOTIFY_SAFE);
  709. X
  710. X    if (do_set(set_options, "compose_icon"))
  711. X    (void) panel_create_item(panel, PANEL_CHOICE,
  712. X        PANEL_ATTRIBUTE_LIST,         choice_args,
  713. X        PANEL_LABEL_IMAGE,
  714. X        panel_button_image(panel, "Close", 5, mush_font),
  715. X        PANEL_CHOICE_STRINGS,
  716. X        "Close to Icon", "Quit", "Help", NULL,
  717. X        PANEL_NOTIFY_PROC,         close_compose,
  718. X        NULL);
  719. X    else
  720. X    (void) panel_create_item(panel, PANEL_BUTTON,
  721. X        PANEL_ATTRIBUTE_LIST,         button_args,
  722. X        PANEL_LABEL_IMAGE,
  723. X        panel_button_image(panel, "Close", 5, mush_font),
  724. X        PANEL_NOTIFY_PROC,         close_frame,
  725. X        NULL);
  726. X
  727. X    (void) panel_create_item(panel, PANEL_CHOICE,
  728. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  729. X    PANEL_LABEL_IMAGE,
  730. X        panel_button_image(panel, "Compose", 7, mush_font),
  731. X    PANEL_CHOICE_STRINGS,         "Help", NULL,
  732. X    PANEL_NOTIFY_PROC,         do_compose,
  733. X    NULL);
  734. X
  735. X    send_item = panel_create_item(panel, PANEL_BUTTON,
  736. X    PANEL_ATTRIBUTE_LIST,         button_args,
  737. X    PANEL_SHOW_ITEM,         FALSE,
  738. X    PANEL_LABEL_IMAGE,
  739. X        panel_button_image(panel, "Send", 4, mush_font),
  740. X    PANEL_NOTIFY_PROC,         do_send,
  741. X    NULL);
  742. X
  743. X    (void) panel_create_item(panel, PANEL_BUTTON,
  744. X    PANEL_ATTRIBUTE_LIST,         button_args,
  745. X    PANEL_SHOW_ITEM,        FALSE,
  746. X    PANEL_LABEL_IMAGE,
  747. X        panel_button_image(panel, "Abort", 5, mush_font),
  748. X    PANEL_NOTIFY_PROC,         abort_mail,
  749. X    NULL);
  750. X
  751. X    (void) panel_create_item(panel, PANEL_CHOICE,
  752. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  753. X    PANEL_SHOW_ITEM,         FALSE,
  754. X    PANEL_LABEL_IMAGE,
  755. X        panel_button_image(panel, "Include", 7, mush_font),
  756. X    PANEL_CHOICE_STRINGS,         "Include Message",
  757. X                    "Forward Message",
  758. X                    "Help", NULL,
  759. X    PANEL_NOTIFY_PROC,         do_include,
  760. X    NULL);
  761. X
  762. X    edit_item = panel_create_item(panel, PANEL_BUTTON,
  763. X    PANEL_ATTRIBUTE_LIST,         button_args,
  764. X    PANEL_SHOW_ITEM,         FALSE,
  765. X    PANEL_LABEL_IMAGE,
  766. X        panel_button_image(panel, "Edit", 4, mush_font),
  767. X    PANEL_NOTIFY_PROC,         do_edit,
  768. X    NULL);
  769. X
  770. X    (void) panel_create_item(panel, PANEL_CHOICE,
  771. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  772. X    PANEL_SHOW_ITEM,        FALSE,
  773. X    PANEL_LABEL_IMAGE,
  774. X        panel_button_image(panel, "Headers", 7, mush_font),
  775. X    PANEL_CHOICE_STRINGS,    
  776. X        "ALL      ~h", "To:      ~t", "Subject: ~s",
  777. X        "Cc:      ~c", "Bcc:     ~b", "Fcc:", NULL,
  778. X    PANEL_NOTIFY_PROC,        tilde_from_menu,
  779. X    NULL);
  780. X
  781. X    sign_item = panel_create_item(panel, PANEL_CHOICE,
  782. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  783. X    PANEL_DISPLAY_LEVEL,        PANEL_ALL,
  784. X    PANEL_SHOW_MENU_MARK,        TRUE,
  785. X    PANEL_SHOW_ITEM,         FALSE,
  786. X    PANEL_LABEL_STRING,        "Autosign:",
  787. X    PANEL_CHOICE_STRINGS,        "Off", "On", NULL,
  788. X    NULL);
  789. X    panel_set_value(sign_item, !!do_set(set_options, "autosign"));
  790. X    /* Create a link to avoid global */
  791. X    panel_set(send_item, PANEL_CLIENT_DATA, sign_item, NULL);
  792. X
  793. X    filename_item = panel_create_item(panel, PANEL_TEXT,
  794. X    PANEL_ATTRIBUTE_LIST,         button_args,
  795. X    PANEL_SHOW_ITEM,        FALSE,
  796. X    PANEL_LABEL_STRING,        "Filename:",
  797. X    PANEL_VALUE_DISPLAY_LENGTH,     30,
  798. X    PANEL_NOTIFY_STRING,         "\033",
  799. X    PANEL_NOTIFY_PROC,         file_dir,
  800. X    NULL);
  801. X
  802. X    (void) panel_create_item(panel, PANEL_CHOICE,
  803. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  804. X    PANEL_SHOW_ITEM,        FALSE,
  805. X    PANEL_CLIENT_DATA,        filename_item,
  806. X    PANEL_LABEL_IMAGE,
  807. X        panel_button_image(panel, "Import", 6, mush_font),
  808. X    PANEL_CHOICE_STRINGS,        "Insert", "Replace", NULL,
  809. X    PANEL_NOTIFY_PROC,        load_from_file,
  810. X    NULL);
  811. X
  812. X    (void) panel_create_item(panel, PANEL_BUTTON,
  813. X    PANEL_ATTRIBUTE_LIST,         button_args,
  814. X    PANEL_SHOW_ITEM,        FALSE,
  815. X    PANEL_CLIENT_DATA,        filename_item,
  816. X    PANEL_LABEL_IMAGE,
  817. X        panel_button_image(panel, "Export", 6, mush_font),
  818. X    PANEL_NOTIFY_PROC,        save_to_file,
  819. X    NULL);
  820. X
  821. X    fortune_item = panel_create_item(panel, PANEL_CHOICE,
  822. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  823. X    PANEL_DISPLAY_LEVEL,        PANEL_ALL,
  824. X    PANEL_SHOW_MENU_MARK,        TRUE,
  825. X    PANEL_SHOW_ITEM,         FALSE,
  826. X    PANEL_LABEL_STRING,        "Fortune:",
  827. X    PANEL_CHOICE_STRINGS,        "Off", "On", NULL,
  828. X    NULL);
  829. X    panel_set_value(fortune_item, !!do_set(set_options, "fortune"));
  830. X    /* Create a link to avoid global */
  831. X    panel_set(sign_item, PANEL_CLIENT_DATA, fortune_item, NULL);
  832. X
  833. X    window_fit_height(panel);
  834. X    return panel;
  835. }
  836. X
  837. #include "glob.h"
  838. X
  839. #ifndef NO_WALK_MENUS
  840. X
  841. static
  842. Menu_item
  843. make_folder_item(path)
  844. char *path;
  845. {
  846. X    Menu_item        mi;
  847. X    Menu_item        sub_mi;
  848. X    Menu        next_menu;
  849. X    char        **names, **np;
  850. X    struct stat     s_buf;
  851. X    char        buf[MAXPATHLEN];
  852. X
  853. X    if (glob(path, "*/{.,..}")) {
  854. X    return NULL;
  855. X    }
  856. X
  857. X    /* don't add a folder to the list if user can't read it */
  858. X    if (stat(path, &s_buf) == -1 || !(s_buf.st_mode & S_IREAD)) {
  859. X    return NULL;
  860. X    }
  861. X    mi = menu_create_item(
  862. X    MENU_STRING,        savestr(basename(trim_filename(path))),
  863. X    MENU_CLIENT_DATA,    NULL,
  864. X    MENU_RELEASE,        /* no value */
  865. X    NULL);
  866. X    if ((s_buf.st_mode & S_IFMT) == S_IFDIR) {
  867. X    int cnt = 0;
  868. X    next_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  869. X    sprintf(buf, "%s/{.*,*}", path);
  870. X    if (filexp(buf, &names) > 0) {
  871. X        for (np = names; np && *np; np++) {
  872. X        if ((sub_mi = make_folder_item(*np)) != NULL) {
  873. X            menu_set(next_menu, MENU_APPEND_ITEM, sub_mi, NULL);
  874. X            ++cnt;
  875. X        }
  876. X        }
  877. X        free_vec(names);
  878. X    }
  879. X    if (! cnt) {
  880. X        menu_destroy(next_menu);
  881. X        menu_set(mi, MENU_INACTIVE, TRUE, NULL);
  882. X    } else {
  883. X        menu_set(mi, MENU_PULLRIGHT, next_menu, NULL);
  884. X    }
  885. X    } else if (test_folder(path, NULL)) {
  886. X    menu_set(mi, MENU_CLIENT_DATA, savestr(path), NULL);
  887. X    } else {
  888. X    menu_destroy(mi);
  889. X    mi = NULL;
  890. X    }
  891. X    return mi;
  892. }
  893. X
  894. static
  895. void
  896. destroy_folder_item(menu_item, menu_type)
  897. Menu_item menu_item;
  898. Menu_attribute menu_type;
  899. {
  900. X    char    *ptr;
  901. X
  902. X    if (menu_type == MENU_ITEM) {
  903. X    if ((ptr = (char *)menu_get(menu_item, MENU_STRING)) != NULL) {
  904. X        free(ptr);
  905. X    }
  906. X    if ((ptr = (char *)menu_get(menu_item, MENU_CLIENT_DATA)) != NULL) {
  907. X        free(ptr);
  908. X    }
  909. X    }
  910. X    return;
  911. }
  912. X
  913. create_folder_menus()
  914. {
  915. X    int       item_number;
  916. X    Menu      menu;
  917. X    Menu_item      menu_item;
  918. X    int       nitems;
  919. X    char     *mbox;
  920. X    char     *tmp = NULL;
  921. X    char     *p;
  922. X    static int      menus_exist = 0;
  923. X
  924. X    if (menus_exist) {
  925. X    /* remove duplicated menu items from save_menu */
  926. X    for (item_number = (int)menu_get(save_menu, MENU_NITEMS) ;
  927. X          item_number > 1 ; --item_number) {
  928. X        menu_set(save_menu, MENU_REMOVE, item_number, NULL);
  929. X    }
  930. X    /* remove duplicated menu items from hdr_save_menu */
  931. X    for (item_number = (int)menu_get(hdr_save_menu, MENU_NITEMS) ;
  932. X          item_number > 1 ; --item_number) {
  933. X        menu_set(save_menu, MENU_REMOVE, item_number, NULL);
  934. X    }
  935. X    menu_destroy_with_proc(hdr_save_menu, destroy_folder_item);
  936. X    menu_destroy_with_proc(save_menu, destroy_folder_item);
  937. X    menu_destroy_with_proc(folder_menu, destroy_folder_item);
  938. X    }
  939. X
  940. X    if (!(p = do_set(set_options, "folder")) || !*p) {
  941. X    p = DEF_FOLDER;
  942. X    }
  943. X    if (p) {
  944. X    int x = 0;
  945. X    tmp = getpath(p, &x);
  946. X    if (x == -1) {
  947. X        if (errno != ENOENT)
  948. X        print("%s: %s\n", p, tmp);
  949. X        tmp = NULL;
  950. X    }
  951. X    }
  952. X    menu = NULL;
  953. X    menu_item = NULL;
  954. X    if (tmp != NULL) {
  955. X    if ((menu_item = make_folder_item(tmp)) != NULL) {
  956. X        if ((menu = menu_get(menu_item, MENU_PULLRIGHT)) != NULL) {
  957. X            /* $folder was a directory, use the pullright
  958. X         * instead of the directory menu item.
  959. X         */
  960. X        /* "unhook" the pullright (so it is not released) */
  961. X        menu_set(menu_item, MENU_PULLRIGHT, NULL, NULL);
  962. X        /* destroy the menu item */
  963. X        menu_destroy_with_proc(menu_item, destroy_folder_item);
  964. X        menu_item = NULL;
  965. X        }
  966. X    }
  967. X    }
  968. X    if (menu == NULL) {
  969. X    menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  970. X    if (menu_item != NULL) {
  971. X        menu_set(menu, MENU_APPEND_ITEM, menu_item, NULL);
  972. X    }
  973. X    }
  974. X
  975. X    /* create save_menu */
  976. X    save_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  977. X    /* add magic first item */
  978. X    mbox = do_set(set_options, "mbox");
  979. X    if (!mbox || !*mbox) {
  980. X    mbox = DEF_MBOX;
  981. X    }
  982. X    menu_item = menu_create_item(
  983. X    MENU_STRING,        savestr(trim_filename(mbox)),
  984. X    MENU_CLIENT_DATA,    savestr(mbox),
  985. X    MENU_RELEASE,        /* no value */
  986. X    NULL);
  987. X    menu_set(save_menu, MENU_APPEND_ITEM, menu_item, NULL);
  988. X    /* copy menu for save_menu */
  989. X    nitems = (int)menu_get(menu, MENU_NITEMS);
  990. X    for (item_number = 1 ; item_number <= nitems ; ++item_number) {
  991. X    menu_set(save_menu,
  992. X        MENU_APPEND_ITEM, menu_get(menu, MENU_NTH_ITEM, item_number),
  993. X        NULL);
  994. X    }
  995. X
  996. X    /* create hdr_save_menu */
  997. X    hdr_save_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  998. X    /* add magic first item */
  999. X    menu_item = menu_create_item(
  1000. X    MENU_STRING,        savestr("use Filename:"),
  1001. X    MENU_CLIENT_DATA,    savestr(""),    /* magic */
  1002. X    MENU_RELEASE,        /* no value */
  1003. X    NULL);
  1004. X    menu_set(hdr_save_menu, MENU_APPEND_ITEM, menu_item, NULL);
  1005. X    /* copy save_menu for hdr_save_menu */
  1006. X    nitems = (int)menu_get(save_menu, MENU_NITEMS);
  1007. X    for (item_number = 1 ; item_number <= nitems ; ++item_number) {
  1008. X    menu_set(hdr_save_menu,
  1009. X        MENU_APPEND_ITEM, menu_get(save_menu, MENU_NTH_ITEM, item_number),
  1010. X        NULL);
  1011. X    }
  1012. X    /* Make sure the header subwindow menu exists so we can tack on a
  1013. X     * pullright for Save.
  1014. X     */
  1015. X    if (! msg_menu) {
  1016. X    get_msg_menu();
  1017. X    }
  1018. X    if ((menu_item = menu_find(msg_menu, MENU_STRING, "Save", NULL))
  1019. X        != NULL) {
  1020. X    menu_set(menu_item, MENU_PULLRIGHT, hdr_save_menu, NULL);
  1021. X    }
  1022. X
  1023. X    /* insert folder-specific initial options to menu */
  1024. X    folder_menu = menu;
  1025. X    menu_item = menu_create_item(
  1026. X    MENU_STRING,        savestr("System Mailbox"),
  1027. X    MENU_CLIENT_DATA,    savestr("%"),
  1028. X    MENU_RELEASE,        /* no value */
  1029. X    NULL);
  1030. X    menu_set(folder_menu, MENU_INSERT, 0, menu_item, NULL);
  1031. X    menu_item = menu_create_item(
  1032. X    MENU_STRING,        savestr("Main Mailbox"),
  1033. X    MENU_CLIENT_DATA,    savestr("&"),
  1034. X    MENU_RELEASE,        /* no value */
  1035. X    NULL);
  1036. X    menu_set(folder_menu, MENU_INSERT, 1, menu_item, NULL);
  1037. X    menu_item = menu_create_item(
  1038. X    MENU_STRING,        savestr("Last Accessed Folder"),
  1039. X    MENU_CLIENT_DATA,    savestr("#"),
  1040. X    MENU_RELEASE,        /* no value */
  1041. X    NULL);
  1042. X    menu_set(folder_menu, MENU_INSERT, 2, menu_item, NULL);
  1043. X
  1044. X    menus_exist = 1;
  1045. X    return;
  1046. }
  1047. X
  1048. static
  1049. walk_menu_event(item, event)
  1050. Panel_item item;
  1051. Event *event;
  1052. {
  1053. X    char     *folder_name;
  1054. X    Menu_item       selection;
  1055. X    Menu      menu;
  1056. X    Panel      panel;
  1057. X    void xx_file_dir();
  1058. X
  1059. X    if (event_id(event) == MS_RIGHT && event_is_down(event)) {
  1060. X    if (item == folder_item) {
  1061. X        menu = folder_menu;
  1062. X        panel = folder_panel;
  1063. X    } else {
  1064. X        menu = save_menu;
  1065. X        panel = save_panel;
  1066. X    }
  1067. X    selection = (Menu_item)menu_show(menu, panel, event, 0);
  1068. X    if (! selection) {
  1069. X        /* no selection was made */
  1070. X        return;
  1071. X    }
  1072. X    if ((folder_name = (char *)menu_get(selection, MENU_CLIENT_DATA))
  1073. X        != NULL) {
  1074. X        xx_file_dir(item, folder_name);
  1075. X    }
  1076. X    } else {
  1077. X    panel_default_handle_event(item, event);
  1078. X    }
  1079. }
  1080. X
  1081. #else /* NO_WALK_MENUS */
  1082. X
  1083. static
  1084. add_path_to_menu(item, path, n)
  1085. Panel_item item;
  1086. char *path;
  1087. int *n;
  1088. {
  1089. X    char        **names, **np;
  1090. X    struct stat     s_buf;
  1091. X    char        buf[MAXPATHLEN];
  1092. X
  1093. X    /* don't add a folder to the list if user can't read it */
  1094. X    if (stat(path, &s_buf) == -1 || !(s_buf.st_mode & S_IREAD))
  1095. X    return;
  1096. X    if ((s_buf.st_mode & S_IFMT) == S_IFDIR) {
  1097. X    sprintf(buf, "%s/{.*,*}", path);
  1098. X    if (filexp(buf, &names) > 0) {
  1099. X        for (np = names; np && *np; np++) {
  1100. X        if (!glob(*np, "*/{.,..}"))
  1101. X            add_path_to_menu(item, *np, n);
  1102. X        }
  1103. X        free_vec(names);
  1104. X    }
  1105. X    } else if (test_folder(path, NULL))
  1106. X    panel_set(item,
  1107. X        PANEL_CHOICE_STRING, (*n)++, savestr(trim_filename(path)),
  1108. X        NULL);
  1109. }
  1110. X
  1111. /*
  1112. X * Open the user's mail folder (either user set or default path) and find all
  1113. X * the files (assumed to be mail folders) and add them to the menu list of
  1114. X * folders to use.
  1115. X */
  1116. add_folder_to_menu(item, n)
  1117. Panel_item item;
  1118. {
  1119. X    char    *tmp = NULL, *p;
  1120. X
  1121. X    if (!(p = do_set(set_options, "folder")) || !*p)
  1122. X    p = DEF_FOLDER;
  1123. X    if (p) {
  1124. X    int x = 0;
  1125. X    tmp = getpath(p, &x);
  1126. X    if (x == -1) {
  1127. X        if (errno != ENOENT)
  1128. X        print("%s: %s\n", p, tmp);
  1129. X        tmp = NULL;
  1130. X    }
  1131. X    }
  1132. X    if (tmp) {
  1133. X    add_path_to_menu(item, tmp, &n);
  1134. X    }
  1135. }
  1136. #endif /* NO_WALK_MENUS */
  1137. SHAR_EOF
  1138. chmod 0644 panels.c ||
  1139. echo 'restore of panels.c failed'
  1140. Wc_c="`wc -c < 'panels.c'`"
  1141. test 22092 -eq "$Wc_c" ||
  1142.     echo 'panels.c: original size 22092, current size' "$Wc_c"
  1143. rm -f _shar_wnt_.tmp
  1144. fi
  1145. # ============= pick.c ==============
  1146. if test -f 'pick.c' -a X"$1" != X"-c"; then
  1147.     echo 'x - skipping pick.c (File already exists)'
  1148.     rm -f _shar_wnt_.tmp
  1149. else
  1150. > _shar_wnt_.tmp
  1151. echo 'x - extracting pick.c (Text)'
  1152. sed 's/^X//' << 'SHAR_EOF' > 'pick.c' &&
  1153. /* @(#)pick.c    2.4    (c) copyright 10/18/86 (Dan Heller) */
  1154. X
  1155. #include "mush.h"
  1156. X
  1157. static int before, after, search_from, search_subj, search_to, xflg, icase;
  1158. static u_long match_priority;
  1159. static char search_hdr[64];
  1160. static int mdy[3];
  1161. static int pick();
  1162. static void month_day_year();
  1163. X
  1164. do_pick(n, argv, list)
  1165. register int n;
  1166. register char **argv, list[];
  1167. {
  1168. X    char ret_list[MAXMSGS_BITS];
  1169. X
  1170. X    if (n > 1 && !strcmp(argv[1], "-?"))
  1171. X    return help(0, "pick", cmd_help);
  1172. X
  1173. X    clear_msg_list(ret_list);
  1174. X    /* if is_pipe, then the messages to search for are already set.
  1175. X     * if not piped, then reverse the bits for all message numbers.
  1176. X     * That is, search EACH message. only those matching will be returned.
  1177. X     */
  1178. X    if (isoff(glob_flags, IS_PIPE))
  1179. X    bitput(ret_list, list, msg_cnt, =~); /* macro, turn on all bits */
  1180. X    /* Use n temporarily as verbosity flag */
  1181. X    n = (!chk_option("quiet", "pick") &&
  1182. X        isoff(glob_flags, DO_PIPE));
  1183. X    if ((n = pick(argv, list, ret_list, n)) == -1)
  1184. X    return -1;
  1185. X    if (istool && isoff(glob_flags, DO_PIPE))
  1186. X    print("%d matches:\n", n);
  1187. X    for (n = 0; n < msg_cnt; n++)
  1188. X    if (msg_bit(ret_list, n)) {
  1189. X        if (isoff(glob_flags, DO_PIPE))
  1190. X        if (istool)
  1191. X            print_more("%d ", n+1);
  1192. X        else
  1193. X            print("%s\n", compose_hdr(n));
  1194. X        set_msg_bit(list, n);
  1195. X    } else
  1196. X        unset_msg_bit(list, n);
  1197. X    return 0;
  1198. }
  1199. X
  1200. /*
  1201. X * search for messages.  Return the number of matches.  Errors such
  1202. X * as internal errors or syntax errors, return -1.
  1203. X * "head" and "tail" are specified using +<num> or -<num> as args.
  1204. X * Both can be specified and the order is significant.
  1205. X *    pick +5 -3
  1206. X * returns the last three of the first five matches.
  1207. X *    pick -3 +2
  1208. X * returns the first two of the last three matches.
  1209. X */
  1210. static int
  1211. pick(argv, list, ret_list, verbose)
  1212. register char **argv, list[], ret_list[];
  1213. {
  1214. X    register char c;
  1215. X    int matches = 0;
  1216. X    char pattern[256];
  1217. X    short head_first, head_cnt, tail_cnt, search = TRUE;
  1218. X    int n;
  1219. X
  1220. X    if (!msg_cnt) {
  1221. X    print("No Messages.\n");
  1222. X    return -1;
  1223. X    }
  1224. X
  1225. X    head_first = TRUE;
  1226. X    head_cnt = tail_cnt = -1;
  1227. X    match_priority = 0;
  1228. X    icase = before = after = search_from = search_subj = search_to = xflg = 0;
  1229. X    mdy[0] = mdy[1] = search_hdr[0] = 0;
  1230. X    while (*argv && *++argv && (**argv == '-' || **argv == '+'))
  1231. X    if (**argv == '+' || isdigit(argv[0][1])) {
  1232. X        if (**argv == '+')
  1233. X        head_cnt = atoi(&argv[0][1]);
  1234. X        else {
  1235. X        tail_cnt = atoi(&argv[0][1]);
  1236. X        if (head_cnt == -1)
  1237. X            head_first = FALSE;
  1238. X        }
  1239. X        if (head_cnt == 0 || tail_cnt == 0) {
  1240. X        print("pick: invalid head/tail number: %s\n", &argv[0][1]);
  1241. X        clear_msg_list(ret_list);
  1242. X        return -1;
  1243. X        }
  1244. X    } else if ((c = argv[0][1]) == 'e') {
  1245. X        if (!*++argv) {
  1246. X        print("usage: -e expression...\n");
  1247. X        return -1;
  1248. X        }
  1249. X        break;
  1250. X    } else switch (c) {
  1251. X        /* user specifies a range */
  1252. X        case 'r': {
  1253. X        int X = 2;
  1254. X        /* if not a pipe, then clear all bits cuz we only want
  1255. X         * to search the message specified here...
  1256. X         * If it is a pipe, then add to the messages searched for.
  1257. X         */
  1258. X        if (isoff(glob_flags, IS_PIPE))
  1259. X            clear_msg_list(list);
  1260. X        /*  "-r10-15"
  1261. X         *     ^argv[1][2]  if NULL, then
  1262. X         * list detached from "r" e.g. "-r" "5-20"
  1263. X         */
  1264. X        if (!argv[0][X])
  1265. X            argv++, X = 0;
  1266. X        (*argv) += X;
  1267. X        n = get_msg_list(argv, list);
  1268. X        (*argv) -= X;
  1269. X        if (n == -1)
  1270. X            return -1;
  1271. X        argv += (n-1); /* we're going to increment another up top */
  1272. X        }
  1273. X        when 'a': {
  1274. X        if ((n = ago_date(++argv)) == -1)
  1275. X            return -1;
  1276. X        argv += n;
  1277. X        }
  1278. X        when 'd':
  1279. X        if (!*++argv) {
  1280. X            print("Specify a date for -%c\n", c);
  1281. X            return -1;
  1282. X        }
  1283. X        if (!date1(*argv))
  1284. X            return -1;
  1285. X        when 's' : case 'f': case 't': case 'h':
  1286. X        if (search_subj + search_from + search_to + *search_hdr > 1) {
  1287. X            print("Specify one of `s', `f', `t' or `h' only\n");
  1288. X            return -1;
  1289. X            }
  1290. X            if (c == 's')
  1291. X            search_subj = 1;
  1292. X        else if (c == 'f')
  1293. X            search_from = 1;
  1294. X        else if (c == 'h')
  1295. X            if (!*++argv)
  1296. X            print("Specify header to search for.\n");
  1297. X            else
  1298. X            (void) lcase_strcpy(search_hdr, *argv);
  1299. X        else
  1300. X            search_to = 1;
  1301. X        when 'p' :    /* Select on priority field */
  1302. X        if (!*++argv || (c = upper(**argv)) < 'A' ||
  1303. X            c > MAX_PRIORITY + 'A') {
  1304. X            print("pick: invalid priority: %s\n", argv[0]);
  1305. X            clear_msg_list(ret_list);
  1306. X            return -1;
  1307. X        }
  1308. X        turnon(match_priority, M_PRIORITY(c - 'A' + 1));
  1309. X        when 'x' : xflg = 1;
  1310. X        when 'i' : icase = 1;
  1311. X        otherwise:
  1312. X        print("pick: unknown flag: %c\n", argv[0][1]);
  1313. X        clear_msg_list(ret_list);
  1314. X        return -1;
  1315. X    }
  1316. X    if (xflg && head_cnt + tail_cnt >= 0) {
  1317. X    print("Can't specify -x and head/tail options together.\n");
  1318. X    return -1;
  1319. X    }
  1320. X    if (!mdy[1]) {
  1321. X    pattern[0] = 0;
  1322. X    (void) argv_to_string(pattern, argv);
  1323. X    if (pattern[0] == '\0' && match_priority == 0 &&
  1324. X        head_cnt + tail_cnt < 0) {
  1325. X        print("No pattern specified\n");
  1326. X        clear_msg_list(ret_list);  /* doesn't matter really */
  1327. X        return -1;
  1328. X    }
  1329. X    }
  1330. X    search = (pattern[0] || mdy[1] || match_priority > 0);
  1331. X    if (verbose) {
  1332. X    if (head_cnt + tail_cnt >= 0) {
  1333. X        print("Finding the ");
  1334. X        if (head_cnt > 0) {
  1335. X        if (head_first)
  1336. X            if (tail_cnt == -1)
  1337. X            print_more("first %d message%s",
  1338. X                head_cnt, head_cnt > 1? "s" : "");
  1339. X            else
  1340. X            print_more("last %d message%s",
  1341. X                tail_cnt, tail_cnt > 1? "s" : "");
  1342. X        else /* there must be a tail_cnt and it comes first */
  1343. X            print_more("first %d message%s",
  1344. X                head_cnt, head_cnt > 1? "s" : "");
  1345. X        } else
  1346. X        print_more("last %d message%s",
  1347. X            tail_cnt, tail_cnt > 1? "s" : "");
  1348. X        if (tail_cnt > 0 && head_cnt > 0)
  1349. X        if (head_first)
  1350. X            print_more(" of the first %d", head_cnt);
  1351. X        else
  1352. X            print_more(" of the last %d", tail_cnt);
  1353. X    } else
  1354. X        print_more("Searching for %smessages",
  1355. X        match_priority > 0 ? "priority " : "");
  1356. X    if (!search) {
  1357. X        if (tail_cnt > 0 && head_cnt > 0)
  1358. X        print_more(" messages");
  1359. X        if (ison(glob_flags, IS_PIPE))
  1360. X        print_more(" from the input list");
  1361. X    } else if (pattern[0]) {
  1362. X        print_more(" that %scontain \"%s\"", (xflg)? "do not ": "",
  1363. X                pattern);
  1364. X        if (search_subj)
  1365. X        print_more(" in subject line");
  1366. X        else if (search_from)
  1367. X        print_more(" from author names");
  1368. X        else if (search_to)
  1369. X        print_more(" from the To: field");
  1370. X        else if (search_hdr[0])
  1371. X        print_more(" from the message header \"%s:\"", search_hdr);
  1372. X    } else if (mdy[1]) {
  1373. X        extern char *month_names[]; /* from dates.c */
  1374. X        print_more(" dated ");
  1375. X        if (before || after)
  1376. X        if (xflg)
  1377. X            print_more("%s ", (!before)? "before": "after");
  1378. X        else
  1379. X            print_more("on or %s ", (before)? "before": "after");
  1380. X        print_more("%s. %d, %d",
  1381. X              month_names[mdy[0]], mdy[1], mdy[2] + 1900);
  1382. X    }
  1383. X    print_more(".\n");
  1384. X    }
  1385. X    if (mdy[1] > 0 && icase)
  1386. X    print("using date: -i flag ignored.\n");
  1387. X    if (!search) {
  1388. X    for (n = 0; n < msg_cnt && (!head_first || matches < head_cnt); n++)
  1389. X        if (msg_bit(list, n))
  1390. X        ++matches, set_msg_bit(ret_list, n);
  1391. X    } else
  1392. X    matches = find_pattern(head_first? head_cnt : msg_cnt,
  1393. X               pattern, list, ret_list);
  1394. X    if (xflg && matches >= 0) {
  1395. X    /* invert items in ret_list that also appear in list */
  1396. X    bitput(list, ret_list, msg_cnt, ^=);
  1397. X    /* there should be a faster way to do this count ... */
  1398. X    for (matches = n = 0; n < msg_cnt; n++)
  1399. X        if (msg_bit(ret_list, n))
  1400. X        ++matches;
  1401. X    }
  1402. X    Debug("matches = %d\n", matches);
  1403. X    if (!matches)
  1404. X    return 0;
  1405. X
  1406. X    /* ok, the list we've got is a list of matched messages.  If "tailing"
  1407. X     * is set, reduce the number of matches to at least tail_cnt.
  1408. X     */
  1409. X    if (tail_cnt >= 0)
  1410. X    for (n = 0; n < msg_cnt && matches > tail_cnt; n++)
  1411. X        if (msg_bit(ret_list, n)) {
  1412. X        Debug("tail: dropping %d\n", n+1);
  1413. X        unset_msg_bit(ret_list, n);
  1414. X        matches--;
  1415. X        }
  1416. X
  1417. X    /* if tailing came before heading, we need to do the heading now. */
  1418. X    if (!head_first && head_cnt >= 0)
  1419. X    for (n = 0; n < msg_cnt; n++)
  1420. X        if (msg_bit(ret_list, n))
  1421. X        if (head_cnt > 0)
  1422. X            head_cnt--;
  1423. X        else {
  1424. X            unset_msg_bit(ret_list, n);
  1425. X            matches--;
  1426. X        }
  1427. X    return matches;
  1428. }
  1429. X
  1430. /*
  1431. X * find_pattern will search thru all the messages set in the check_list
  1432. X * until the list runs out or "cnt" has been exhasted.  ret_list contains
  1433. X * the list of messages which have matched the pattern.
  1434. X * return -1 for internal error or # of pattern matches.
  1435. X */
  1436. find_pattern(cnt, p, check_list, ret_list)
  1437. int cnt;
  1438. register char *p;
  1439. char check_list[], ret_list[];
  1440. {
  1441. X    register int n, val, i; /* val is return value from regex or re_exec */
  1442. X    int matches = 0;
  1443. X    long bytes = 0;
  1444. X    char buf[HDRSIZ];
  1445. X    static char *err = (char *)-1;
  1446. #ifdef REGCMP
  1447. X    char *regcmp(), *regex();
  1448. #else /* REGCMP */
  1449. X    char *re_comp();
  1450. #endif /* REGCMP */
  1451. X
  1452. X    if (p && *p == '\\')
  1453. X    p++;  /* take care of escaping special cases (`-', `\') */
  1454. X
  1455. X    /* specify what we're looking for */
  1456. X    if (p && *p) {
  1457. X    if (icase)
  1458. X        p = lcase_strcpy(buf, p);
  1459. #ifdef REGCMP
  1460. X    if (err && p)
  1461. X        xfree(err);
  1462. X    if (p && !(err = regcmp(p, NULL))) {
  1463. X        print("regcmp error: %s\n", p);
  1464. X        clear_msg_list(ret_list);
  1465. X        return -1;
  1466. X    }
  1467. #else /* REGCMP */
  1468. X    if (err = re_comp(p)) {
  1469. X        print("re_comp error: %s\n", err);
  1470. X        clear_msg_list(ret_list);
  1471. X        return -1;
  1472. X    }
  1473. #endif /* REGCMP */
  1474. X    } else if (err == (char *)-1 && mdy[1] <= 0 && match_priority == 0) {
  1475. X    print("No previous regular expression\n");
  1476. X    clear_msg_list(ret_list);  /* doesn't matter really */
  1477. X    return -1;
  1478. X    }
  1479. X    /* start searching: set bytes, and message number: n */
  1480. X    for (n = 0; cnt && n < msg_cnt; n++)
  1481. X    if (msg_bit(check_list, n)) {
  1482. X        if (match_priority > 0) {
  1483. X        if (msg[n].m_flags & match_priority)
  1484. X            ++matches, set_msg_bit(ret_list, n);
  1485. X        continue;
  1486. X        }
  1487. X        if (mdy[1] > 0) {
  1488. X        int msg_mdy[3];
  1489. X        if (ison(glob_flags, DATE_RECV))
  1490. X            p = msg[n].m_date_recv;
  1491. X        else
  1492. X            p = msg[n].m_date_sent;
  1493. X        /* Ick -- fix this mdy thing asap */
  1494. X        month_day_year(p, &msg_mdy[0], &msg_mdy[1], &msg_mdy[2]);
  1495. X        Debug("checking %d's date: %d-%d-%d  ",
  1496. X                 n+1, msg_mdy[0]+1, msg_mdy[1], msg_mdy[2]);
  1497. X        /* start at year and wrap around.
  1498. X         * only when match the day (4), check for == (match)
  1499. X         */
  1500. X        for (i = 2; i < 5; i++)
  1501. X            if (before && msg_mdy[i%3] < mdy[i%3]
  1502. X            ||  after  && msg_mdy[i%3] > mdy[i%3]
  1503. X            ||  i == 4 && (msg_mdy[i%3] == mdy[i%3])) {
  1504. X                Debug("matched (%s).\n",
  1505. X                (i == 2)? "year" : (i == 3)? "month" : "day");
  1506. X                set_msg_bit(ret_list, n);
  1507. X                cnt--, matches++;
  1508. X                break;
  1509. X            } else if (msg_mdy[i%3] != mdy[i%3]) {
  1510. X            Debug("failed.\n");
  1511. X            break;
  1512. X            }
  1513. X        continue;
  1514. X        }
  1515. X        /* we must have the right date -- if we're searching for a
  1516. X         * string, find it.
  1517. X         */
  1518. X        (void) msg_get(n, NULL, 0);
  1519. X        bytes = 0;
  1520. X        while (bytes < msg[n].m_size) {
  1521. X        if (!search_subj && !search_from && !search_to &&
  1522. X            !*search_hdr && !(p = fgets(buf, sizeof buf, tmpf)))
  1523. X            break;
  1524. X        else if (search_subj) {
  1525. X            if (!(p = header_field(n, "subject")))
  1526. X            break;
  1527. X        } else if (search_from) {
  1528. X            if (!(p = header_field(n, "from"))) {
  1529. X            /*
  1530. X             * Check for MSG_SEPARATOR here?  Maybe not...
  1531. X             */
  1532. X            register char *p2;
  1533. X            (void) msg_get(n, NULL, 0);
  1534. X            if (!(p2 = fgets(buf, sizeof buf, tmpf)) ||
  1535. X                !(p = index(p2, ' ')))
  1536. X                continue;
  1537. X            p++;
  1538. X            if (p2 = any(p, " \t"))
  1539. X                *p2 = 0;
  1540. X            }
  1541. X        } else if (search_to) {
  1542. X            if (!(p = header_field(n, "to")) &&
  1543. X                !(p = header_field(n, "apparently-to")))
  1544. X            break;
  1545. X        } else if (*search_hdr) {
  1546. X            if (!(p = header_field(n, search_hdr)))
  1547. X            break;
  1548. X        }
  1549. X        if (icase)
  1550. X            p = lcase_strcpy(buf, p);
  1551. #ifdef REGCMP
  1552. X        val = !!regex(err, p, NULL); /* convert value to a boolean */
  1553. #else /* REGCMP */
  1554. X        val = re_exec(p);
  1555. #endif /* REGCMP */
  1556. X        if (val == -1) {   /* doesn't apply in system V */
  1557. X            print("Internal error for pattern search.\n");
  1558. X            clear_msg_list(ret_list); /* it doesn't matter, really */
  1559. X            return -1;
  1560. X        }
  1561. X        if (val) {
  1562. X            set_msg_bit(ret_list, n);
  1563. X            cnt--, matches++;
  1564. X            break;
  1565. X        }
  1566. X        if (search_subj || search_from || search_to || *search_hdr)
  1567. X            break;
  1568. X        else
  1569. X            bytes += strlen(p);
  1570. X        }
  1571. X    }
  1572. X    return matches;
  1573. }
  1574. X
  1575. #ifdef CURSES
  1576. /*
  1577. X * search for a pattern in composed message headers -- also see next function
  1578. X * flags ==  0   forward search (prompt).
  1579. X * flags == -1   continue search (no prompt).
  1580. X * flags ==  1   backward search (prompt).
  1581. X */
  1582. search(flags)
  1583. register int flags;
  1584. {
  1585. X    register char   *p;
  1586. X    char           pattern[128];
  1587. X    register int    this_msg = current_msg, val = 0;
  1588. X    static char     *err = (char *)-1, direction;
  1589. X    SIGRET        (*oldint)(), (*oldquit)();
  1590. #ifdef REGCMP
  1591. X    char *regcmp();
  1592. #else /* REGCMP */
  1593. X    char *re_comp();
  1594. #endif /* REGCMP */
  1595. X
  1596. X    if (msg_cnt <= 1) {
  1597. X    print("Not enough messages to invoke a search.\n");
  1598. X    return 0;
  1599. X    }
  1600. X    pattern[0] = '\0';
  1601. X    if (flags == -1)
  1602. X    print("continue %s search...", direction? "forward" : "backward");
  1603. X    else
  1604. X    print("%s search: ", flags? "backward" : "forward");
  1605. X    if (flags > -1)
  1606. X    if (Getstr(pattern, COLS-18, 0) < 0)
  1607. X        return 0;
  1608. X    else
  1609. X        direction = !flags;
  1610. #ifdef REGCMP
  1611. X    if (err && *pattern)
  1612. X    xfree(err);
  1613. X    else if (err == (char *)-1 && !*pattern) {
  1614. X    print("No previous regular expression.");
  1615. X    return 0;
  1616. X    }
  1617. X    if (*pattern && !(err = regcmp(pattern, NULL))) {
  1618. X    print("Error in regcmp in %s", pattern);
  1619. X    return 0;
  1620. X    }
  1621. #else /* REGCMP */
  1622. X    if (err = re_comp(pattern)) {
  1623. X    print(err);
  1624. X    return 0;
  1625. X    }
  1626. #endif /* REGCMP */
  1627. X    move(LINES-1, 0), refresh();
  1628. X    on_intr();
  1629. X
  1630. X    do  {
  1631. X    if (direction)
  1632. X        current_msg = (current_msg+1) % msg_cnt;
  1633. X    else
  1634. X        if (--current_msg < 0)
  1635. X        current_msg = msg_cnt-1;
  1636. X    p = compose_hdr(current_msg);
  1637. #ifdef REGCMP
  1638. X    val = !!regex(err, p, NULL); /* convert value to a boolean */
  1639. #else /* REGCMP */
  1640. X    val = re_exec(p);
  1641. #endif /* REGCMP */
  1642. X    if (val == -1)     /* doesn't apply in system V */
  1643. X        print("Internal error for pattern search.\n");
  1644. X    } while (!val && current_msg != this_msg && isoff(glob_flags, WAS_INTR));
  1645. X
  1646. X    if (ison(glob_flags, WAS_INTR)) {
  1647. X    print("Pattern search interrupted.");
  1648. X    current_msg = this_msg;
  1649. X    } else if (val == 0)
  1650. X    print("Pattern not found.");
  1651. X
  1652. X    off_intr();
  1653. X    return val;
  1654. }
  1655. #endif /* CURSES */
  1656. X
  1657. /*
  1658. X * Get just the month, day, and year from a date.
  1659. X * This is a temporary measure until the date compares in pick()
  1660. X * can be overhauled.  It really should be in dates.c, but ...
  1661. X */
  1662. static
  1663. void
  1664. month_day_year(date, month, day, year)
  1665. char *date;
  1666. int *month, *day, *year;
  1667. {
  1668. X    long gmt;
  1669. X    char unused[4], zone[8];
  1670. X    struct tm *t;
  1671. X    extern long getzoff();
  1672. X
  1673. X    (void) sscanf(date, "%ld%3c%s", &gmt, unused, zone);
  1674. X    gmt += getzoff(zone);
  1675. X    t = gmtime(&gmt);
  1676. X    *month = t->tm_mon;
  1677. X    *day = t->tm_mday;
  1678. X    *year = t->tm_year;
  1679. }
  1680. X
  1681. /*
  1682. X * parse a user given date string and set mdy[] array with correct
  1683. X * values.  Return 0 on failure.
  1684. X */
  1685. date1(p)
  1686. register char *p;
  1687. {
  1688. X    register char *p2;
  1689. X    long      t;
  1690. X    int       i;
  1691. X    struct tm       *today;
  1692. X
  1693. X    if (*p == '-' || *p == '+') {
  1694. X    before = !(after = *p == '+');
  1695. X    skipspaces(1);
  1696. X    }
  1697. X    if (!isdigit(*p) && *p != '/') {
  1698. X    print("syntax error on date: \"%s\"\n", p);
  1699. X    return 0;
  1700. X    }
  1701. X    (void) time (&t);
  1702. X    today = localtime(&t);
  1703. X    for (i = 0; i < 3; i++)
  1704. X    if (!p || !*p || *p == '/') {
  1705. X        switch(i) {   /* default to today's date */
  1706. X        case 0: mdy[0] = today->tm_mon;
  1707. X        when 1: mdy[1] = today->tm_mday;
  1708. X        when 2: mdy[2] = today->tm_year;
  1709. X        }
  1710. X        if (p && *p)
  1711. X        p++;
  1712. X    } else {
  1713. X        p2 = (*p)? index(p+1, '/') : NULL;
  1714. X        mdy[i] = atoi(p); /* atoi will stop at the '/' */
  1715. X        if (i == 0 && (--(mdy[0]) < 0 || mdy[0] > 11)) {
  1716. X        print("Invalid month: %s\n", p);
  1717. X        return 0;
  1718. X        } else if (i == 1 && (mdy[1] < 1 || mdy[1] > 31)) {
  1719. X        print("Invalid day: %s\n", p);
  1720. X        return 0;
  1721. X        }
  1722. X        if (p = p2) /* set p to p2 and check to see if it's valid */
  1723. X        p++;
  1724. X    }
  1725. X    return 1;
  1726. }
  1727. X
  1728. /*
  1729. X * Parse arguments specifying days/months/years "ago" (relative to today).
  1730. X * Legal syntax: -ago [+-][args]
  1731. X *    where "args" is defined to be:
  1732. X *    [0-9]+[ ]*[dD][a-Z]*[ ,]*[0-9]+[mM][a-Z]*[ ,]*[0-9]+[ ]*[yY][a-Z]*
  1733. X *    1 or more digits, 0 or more spaces, d or D followed by 0 or more chars,
  1734. X *    0 or more whitespaces or commas, repeat for months and years...
  1735. X * Examples:
  1736. X *    1 day, 2 months, 0 years
  1737. X *    2 weeks 1 year
  1738. X *    10d, 5m
  1739. X *    3w
  1740. SHAR_EOF
  1741. true || echo 'restore of pick.c failed'
  1742. fi
  1743. echo 'End of  part 19'
  1744. echo 'File pick.c is continued in part 20'
  1745. echo 20 > _shar_seq_.tmp
  1746. exit 0
  1747. exit 0 # Just in case...
  1748. -- 
  1749. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1750. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1751. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1752. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1753.