home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume12 / mush / part10 < prev    next >
Encoding:
Text File  |  1990-05-05  |  54.2 KB  |  1,719 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v12i038: Mail User's Shell, Part10/19
  3. from: argv@Eng.Sun.COM (Dan Heller)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 12, Issue 38
  7. Submitted-by: argv@Eng.Sun.COM (Dan Heller)
  8. Archive-name: mush/part10
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # If this archive is complete, you will see the following message at the end:
  17. #        "End of archive 10 (of 19)."
  18. # Contents:  mush/curses.c mush/mush.h mush/version.h
  19. # Wrapped by argv@turnpike on Wed May  2 13:59:31 1990
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'mush/curses.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'mush/curses.c'\"
  23. else
  24. echo shar: Extracting \"'mush/curses.c'\" \(28433 characters\)
  25. sed "s/^X//" >'mush/curses.c' <<'END_OF_FILE'
  26. X/* @(#)curses.c    (c) copyright 3/18/87 (Dan Heller) */
  27. X
  28. X/* curses.c -- routine to deal with the curses interface */
  29. X#ifdef CURSES
  30. X
  31. X#include "mush.h"
  32. X#include "bindings.h"
  33. X
  34. Xcurses_init(argc, argv)
  35. Xregister char **argv;
  36. X{
  37. X    char buf[80];
  38. X    extern char *UP, ttytype[];
  39. X
  40. X    if (argv && *++argv && !strcmp(*argv, "-?"))
  41. X    return help(0, "curses", cmd_help);
  42. X#ifdef SUNTOOL
  43. X    if (istool) {
  44. X    print("Sorry, can't change to curses mode from tool.\n");
  45. X    return -1;
  46. X    } else
  47. X#endif /* SUNTOOL */
  48. X    if (!is_shell) {
  49. X    /*
  50. X     * Can't start curses, but we can prepare to.
  51. X     * Also allow -C switch to be shut off.
  52. X     */
  53. X    if (argv && *argv && !lcase_strncmp(*argv, "off", -1))
  54. X        turnoff(glob_flags, PRE_CURSES);
  55. X    else
  56. X        turnon(glob_flags, PRE_CURSES);
  57. X    return 0;
  58. X    } else if (argc && (iscurses || ison(glob_flags, PRE_CURSES))) {
  59. X    print("You are already using curses mode.\n");
  60. X    return -1;
  61. X    } else if (ison(glob_flags, IS_GETTING)) {
  62. X    print("Finish your letter first.\n");
  63. X    return -1;
  64. X    }
  65. X
  66. X#ifndef attrset        /* terminfo version of curses */
  67. X    /* you can not start curses in no echo mode.. must be in normal mode */
  68. X    echom();
  69. X    nocrmode();
  70. X#endif /* attrset */
  71. X    (void) initscr();
  72. X#ifdef SIGCONT
  73. X    /* initscr will play with signals -- make sure they're set right. */
  74. X    (void) signal(SIGTSTP, stop_start);
  75. X    (void) signal(SIGCONT, stop_start);
  76. X#endif /* SIGCONT */
  77. X#if !defined(SYSV) && !defined(USG)
  78. X    if (!UP || !*UP)
  79. X#else /* ~SYSV && ~USG */
  80. X    if (!stdscr)
  81. X#endif /* ~SYSV && ~USG */
  82. X         {
  83. X    print("Terminal type %s can not use the curses interface.\n", ttytype);
  84. X    return -1;
  85. X    }
  86. X    iscurses = TRUE;
  87. X    noechom(); /* reset tty state -- */
  88. X    crmode(); /* do not use "echo_on/off()" */
  89. X    scrollok(stdscr, TRUE);
  90. X    /* if the user hasn't set his screen explicitly, set it for him */
  91. X    set_screen_size();
  92. X    if (crt > LINES - 1 || !do_set(set_options, "crt")) {
  93. X    crt = LINES;
  94. X    (void)cmd_line(sprintf(buf, "\\set screen = %d crt = %d", screen, crt),
  95. X        msg_list);
  96. X    } else
  97. X    (void)cmd_line(sprintf(buf, "\\set screen = %d", screen), msg_list);
  98. X    if (argc) {
  99. X    (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1), msg_list);
  100. X    (void) curses_help_msg(TRUE);
  101. X    }
  102. X    if (!do_set(set_options, "no_reverse"))
  103. X    turnon(glob_flags, REV_VIDEO);
  104. X    turnoff(glob_flags, CONT_PRNT);
  105. X    return 0; /* doesn't affect messages */
  106. X}
  107. X
  108. Xstruct cmd_map *active_cmd;    /* See bindings.h for description */
  109. X
  110. X/*
  111. X * get input in cbreak mode and execute the appropriate command.
  112. X * when the command is done (usually), the user is prompted to
  113. X * hit any key to continue. At this point, the user may enter a
  114. X * new command so no screen refreshing needs to be done. This
  115. X * new command is returned to caller and may be passed back.
  116. X *
  117. X * The flag CNTD_CMD (continued command) is set if
  118. X * this routine is called with the passed parameter (c) != 0. If
  119. X * so, then the character passed is the character input by the
  120. X * user at the last "hit return" prompt indicating that he wants
  121. X * to execute a new command and not draw the screen.
  122. X *
  123. X * CNTD_CMD is also set if the command that the user invokes
  124. X * causes any sort of output that requires a screen refresh.  The
  125. X * variable redo is set to 1 if the header page not only requires
  126. X * redrawing, but updating ... (new call to do_hdrs)
  127. X *
  128. X * calls that say: print("%s", compose_hdr(current_msg)) are constructed
  129. X * that way because if the header has a `%' in it, then print will try to
  130. X * expand it.
  131. X */
  132. Xcurses_command(c)
  133. Xregister int c;
  134. X{
  135. X    char    buf[BUFSIZ], file[128], list[128];
  136. X    int     n, curlin;
  137. X    static int  redo = 0;  /* set if headers should be redrawn */
  138. X
  139. X    if (c != 0)
  140. X    turnon(glob_flags, CNTD_CMD);
  141. X    else
  142. X    turnoff(glob_flags, CNTD_CMD);
  143. X    clear_msg_list(msg_list); /* play it safe */
  144. X    if (isoff(glob_flags, CNTD_CMD)) {
  145. X    (void) check_new_mail();
  146. X    curlin = max(1, current_msg - n_array[0] + 1);
  147. X    scrn_line(curlin, buf);
  148. X    if (ison(glob_flags, REV_VIDEO) && msg_cnt)
  149. X        STANDOUT(curlin, 0, buf);
  150. X    mail_status(0);
  151. X    move(curlin, 0), refresh();
  152. X    /* reprint to remove reverse video from current line (don't refresh) */
  153. X    if (ison(glob_flags, REV_VIDEO))
  154. X        mvaddstr(curlin, 0, buf);
  155. X    c = getcmd(); /* get input AFTER line redrawn without reverse video */
  156. X    }
  157. X    buf[0] = list[0] = file[0] = '\0';
  158. X
  159. X    if (c == C_WRITE_LIST || c == C_SAVE_LIST || c == C_COPY_LIST
  160. X       || c == C_DELETE_LIST || c == C_UNDEL_LIST) {
  161. X    if (msg_cnt < 1) {
  162. X        mac_flush();
  163. X        print("Not enough messages.");
  164. X        c = C_NULL;
  165. X    } else if (c == C_DELETE_LIST && ison(glob_flags, READ_ONLY)) {
  166. X        mac_flush();
  167. X        print("Folder is read-only.");
  168. X        c = C_NULL;
  169. X    } else if (!curses_msg_list(sprintf(buf, "%s msg list: ",
  170. X        (c == C_WRITE_LIST)? "write" : (c == C_SAVE_LIST)?  "save" :
  171. X        (c == C_COPY_LIST)? "copy" :
  172. X        (c == C_DELETE_LIST)? "delete" : "undelete"), list, msg_list))
  173. X        c = C_NULL;
  174. X    if (ison(glob_flags, CNTD_CMD))
  175. X        putchar('\n');
  176. X    }
  177. X
  178. X    /* first do non-mail command type stuff */
  179. X    switch (c) {
  180. X    case C_ERROR :
  181. X        bell();
  182. X        mac_flush();
  183. X
  184. X    when C_NULL :
  185. X        if (isoff(glob_flags, CNTD_CMD))
  186. X        bell();
  187. X
  188. X    /* goto a specific message number */
  189. X    when C_GOTO_MSG :
  190. X        if (curses_msg_list(strcpy(buf, "goto msg: "), list, msg_list)) {
  191. X        /*
  192. X         * Reset the current message in case a 
  193. X         * backquoted command (like `from`) changed it
  194. X         */
  195. X        n = current_msg;
  196. X        do if (++n >= msg_cnt)
  197. X            n = 0;
  198. X        while (n != current_msg && !msg_bit(msg_list, n));
  199. X        if (n == current_msg && !msg_bit(msg_list, n)) {
  200. X            mac_flush(); /* bail out if in macro processing */
  201. X            print("Message not found.");
  202. X        }
  203. X        else if ((current_msg = n) < n_array[0]
  204. X            || n > n_array[screen-1])
  205. X            redo = 1;
  206. X        } else {
  207. X        mac_flush();
  208. X        bell();
  209. X        }
  210. X        if (ison(glob_flags, CNTD_CMD) && msg_cnt)
  211. X        print("%-.*s", COLS-2, compose_hdr(current_msg));
  212. X        if (ison(glob_flags, CNTD_CMD))
  213. X        putchar('\n');
  214. X
  215. X    /* screen optimization stuff */
  216. X    when C_REVERSE :
  217. X        if (ison(glob_flags, REV_VIDEO))
  218. X        turnoff(glob_flags, REV_VIDEO);
  219. X        else
  220. X        turnon(glob_flags, REV_VIDEO);
  221. X
  222. X    when C_REDRAW : redo = 1;
  223. X
  224. X    /*
  225. X     * screen movement
  226. X     */
  227. X    when C_NEXT_MSG :
  228. X        if (current_msg + 2 > msg_cnt ||
  229. X        isoff(glob_flags, CNTD_CMD) && curlin == LINES-2) {
  230. X        mac_flush();    /* Bail out if in macro processing */
  231. X        bell();        /* reached the end */
  232. X        } else {
  233. X        if (ison(glob_flags, CNTD_CMD)) {
  234. X            if (++current_msg > n_array[screen-1])
  235. X            redo = 1;
  236. X            print("%-.*s", COLS-2, compose_hdr(current_msg));
  237. X            putchar('\n');
  238. X        } else {
  239. X            if (++current_msg > n_array[screen-1])
  240. X            n_array[screen++] = current_msg;
  241. X            move(++curlin, 0);
  242. X            printw("%-.*s", COLS-2, compose_hdr(current_msg));
  243. X            clrtoeol();
  244. X        }
  245. X        }
  246. X
  247. X    when C_PREV_MSG :
  248. X        if (isoff(glob_flags, CNTD_CMD) && curlin == 1 || current_msg == 0)
  249. X        {
  250. X        mac_flush();    /* Bail out if in macro processing */
  251. X        bell();      /* at the beginning */
  252. X        } else {
  253. X        if (--current_msg < n_array[0])
  254. X            redo = 1;
  255. X        if (ison(glob_flags, CNTD_CMD)) {
  256. X            print("%-.*s", COLS-2, compose_hdr(current_msg));
  257. X            putchar('\n');
  258. X        }
  259. X        }
  260. X
  261. X    when C_FIRST_MSG : case C_LAST_MSG :
  262. X        if (!msg_cnt) {
  263. X        mac_flush();
  264. X        bell();
  265. X        break;
  266. X        }
  267. X        n = current_msg;
  268. X        move(LINES-1, 0), refresh();
  269. X        if (c == C_FIRST_MSG && (current_msg = 0) < n_array[0] ||
  270. X        c == C_LAST_MSG && (current_msg = msg_cnt-1)> n_array[screen-1])
  271. X        if (isoff(glob_flags, CNTD_CMD))
  272. X            (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1),
  273. X                 msg_list);
  274. X        else
  275. X            redo = 1;
  276. X        if (ison(glob_flags, CNTD_CMD) && n != current_msg)
  277. X        print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
  278. X
  279. X    /* top and bottom of headers screen */
  280. X    when C_TOP_PAGE : case C_BOTTOM_PAGE :
  281. X        if (msg_cnt && isoff(glob_flags, CNTD_CMD))
  282. X        if (c == C_TOP_PAGE)
  283. X            current_msg = n_array[0];
  284. X        else
  285. X            current_msg = min(n_array[screen-1], msg_cnt-1);
  286. X        else {
  287. X        mac_flush();
  288. X        bell();
  289. X        }
  290. X
  291. X    when C_NEXT_SCREEN : /* next page */
  292. X        move(LINES-1, 0), refresh();
  293. X        if (msg_cnt-1 > n_array[screen-1]) {
  294. X        clear();
  295. X        set_screen_size();
  296. X        (void) cmd_line(strcpy(buf, "\\headers +"), msg_list);
  297. X        if (current_msg < n_array[0])
  298. X            current_msg = n_array[0];
  299. X        (void) curses_help_msg(TRUE);
  300. X        return redo = 0;
  301. X        } else {
  302. X        mac_flush();
  303. X        bell();
  304. X        }
  305. X
  306. X    when C_PREV_SCREEN : /* previous page */
  307. X        move(LINES-1, 0), refresh();
  308. X        if (n_array[0] > 0) {
  309. X        clear();
  310. X        set_screen_size();
  311. X        (void) cmd_line(strcpy(buf, "\\headers -"), msg_list);
  312. X        if (current_msg > n_array[screen-1])
  313. X            current_msg = n_array[screen-1];
  314. X        (void) curses_help_msg(TRUE);
  315. X        return redo = 0;
  316. X        } else {
  317. X        mac_flush();
  318. X        bell();
  319. X        }
  320. X
  321. X    /* read from/save to record file (.mushrc) */
  322. X    when C_SOURCE : case C_SAVEOPTS : {
  323. X        int argc;
  324. X        char *argv[3];
  325. X        print("%s filename [default]: ",
  326. X        (c == C_SOURCE)? "source" : "save options to");
  327. X        argc = Getstr(file, LINES-40, 0);
  328. X        clr_bot_line();
  329. X        if (argc < 0)
  330. X        break;
  331. X        if (argc > 0)
  332. X        argv[1] = file, argc = 2;
  333. X        else
  334. X        argc = 1;
  335. X        argv[argc] = NULL;
  336. X        turnon(glob_flags, PRE_CURSES);
  337. X        if (c == C_SOURCE) {
  338. X        (void) source(argc, argv);
  339. X        mac_flush(); /* can't change things in mid-macro */
  340. X        redo = isoff(glob_flags, CNTD_CMD);
  341. X        } else
  342. X        (void) save_opts(argc, argv);
  343. X        turnoff(glob_flags, PRE_CURSES);
  344. X    }
  345. X
  346. X    /*
  347. X     * search commands
  348. X     */
  349. X    when C_NEXT_SEARCH : case C_PREV_SEARCH : case C_CONT_SEARCH :
  350. X        if (c != C_CONT_SEARCH)
  351. X        c = search(0 + (c == C_PREV_SEARCH));
  352. X        else
  353. X        c = search(-1);
  354. X        if (ison(glob_flags, CNTD_CMD))
  355. X        putchar('\n');
  356. X        if (c == 0)
  357. X        break;
  358. X        if (ison(glob_flags, CNTD_CMD))
  359. X        print("%-.*s",COLS-2, compose_hdr(current_msg)), putchar('\n');
  360. X        if (n_array[0] > current_msg || n_array[screen-1] < current_msg) {
  361. X        redo = 1;
  362. X        if (isoff(glob_flags, CNTD_CMD))
  363. X            (void) cmd_line(sprintf(buf, "\\headers %d",
  364. X                        current_msg+1), msg_list);
  365. X        }
  366. X
  367. X    /*
  368. X     * actions on messages
  369. X     */
  370. X    /* delete/undelete */
  371. X    when C_DELETE_MSG : case C_DELETE_LIST :
  372. X    case C_UNDEL_MSG : case C_UNDEL_LIST :
  373. X        if (!msg_cnt) {
  374. X        print("No messages.");
  375. X        if (ison(glob_flags, CNTD_CMD))
  376. X            putchar('\n');
  377. X        break;
  378. X        }
  379. X        if (ison(glob_flags, READ_ONLY)) {
  380. X        mac_flush();
  381. X        print("Folder is read-only.");
  382. X        if (ison(glob_flags, CNTD_CMD))
  383. X            putchar('\n');
  384. X        break;
  385. X        }
  386. X        Debug("current message = %d", current_msg + 1);
  387. X        if (!*list)
  388. X        set_msg_bit(msg_list, current_msg);
  389. X        turnon(glob_flags, DO_UPDATE);
  390. X        for (n = 0; n < msg_cnt; n++)
  391. X        if (msg_bit(msg_list, n)) {
  392. X            if (c == C_DELETE_MSG || c == C_DELETE_LIST)
  393. X            turnon(msg[n].m_flags, DELETE);
  394. X            else
  395. X            turnoff(msg[n].m_flags, DELETE);
  396. X            if (isoff(glob_flags, CNTD_CMD) && (msg_cnt < screen ||
  397. X            n >= n_array[0] && n <= n_array[screen-1])) {
  398. X            move(max(1, n - n_array[0] + 1), 0);
  399. X            printw("%-.*s", COLS-1, compose_hdr(n));
  400. X            } else
  401. X            redo = 1;
  402. X        }
  403. X        if (ison(glob_flags, CNTD_CMD) || *list) {
  404. X        /* print(), THEN putchar() -- overwrite line */
  405. X        if (ison(glob_flags, CNTD_CMD)) {
  406. X            print("%sdeleted %s",
  407. X            (c == C_DELETE_MSG || c == C_DELETE_LIST)? "":"un", list);
  408. X            putchar('\n');
  409. X        }
  410. X        if (c == C_DELETE_MSG || c == C_DELETE_LIST) {
  411. X            if (ison(msg[current_msg].m_flags, DELETE) ||
  412. X                ison(msg[current_msg].m_flags, SAVED))
  413. X            (void) next_msg();
  414. X            if (isoff(msg[current_msg].m_flags, DELETE) &&
  415. X                do_set(set_options, "autoprint"))
  416. X            return C_DISPLAY_MSG;
  417. X        }
  418. X        if (ison(glob_flags, CNTD_CMD))
  419. X            puts(compose_hdr(current_msg));
  420. X        else if (current_msg < n_array[0]
  421. X            || current_msg > n_array[screen-1])
  422. X            redo = 1;
  423. X        }
  424. X
  425. X    /*
  426. X     * write/save messages.  If a list is necessary, the user already
  427. X     * entered it above since he must have used a capital letter. If so,
  428. X     * list will contain good data (already been validated above).
  429. X     * if a list is given, set iscurses to 0 so that print statements
  430. X     * will scroll and the user sees the multiple output. else, one
  431. X     * line can go on the bottom line just fine.
  432. X     */
  433. X    when C_WRITE_MSG : case C_SAVE_MSG : case C_COPY_MSG :
  434. X    case C_WRITE_LIST : case C_SAVE_LIST : case C_COPY_LIST : {
  435. X        register char *p =
  436. X        (c == C_WRITE_MSG || c == C_WRITE_LIST)? "write" :
  437. X        (c == C_SAVE_MSG  || c == C_SAVE_LIST)? "save" : "copy";
  438. X        if (!msg_cnt) {
  439. X        print("No messages.");
  440. X        if (ison(glob_flags, CNTD_CMD))
  441. X            putchar('\n');
  442. X        break;
  443. X        }
  444. X        print(sprintf(buf, "filename to %s%s: ", p,
  445. X        (c != C_WRITE_MSG && c != C_WRITE_LIST)? " [mbox]" : ""));
  446. X        if (Getstr(file, COLS-1-strlen(buf), 0) >= 0) {
  447. X        char *argv[3];
  448. X        clr_bot_line();
  449. X        argv[0] = strcpy(buf, p);
  450. X        p = file; skipspaces(0);
  451. X        argv[1] = (*p) ? p : NULL;
  452. X        argv[2] = NULL;
  453. X        if (!*list)
  454. X            set_msg_bit(msg_list, current_msg);
  455. X        move(LINES-1, 0), refresh();
  456. X        if (*list)
  457. X            iscurses = FALSE;
  458. X        /* Turn on piping to make save_msg look at msg_list */
  459. X        turnon(glob_flags, IS_PIPE);
  460. X        if (save_msg(1 + (*file != '\0'), argv, msg_list) < 0)
  461. X            *list = 0;
  462. X        turnoff(glob_flags, IS_PIPE);
  463. X        if (ison(glob_flags, CNTD_CMD))
  464. X            redo = 1, putchar('\n'), puts(compose_hdr(current_msg));
  465. X        if (*list)
  466. X            iscurses = redo = TRUE, turnon(glob_flags, CNTD_CMD);
  467. X        else if (isoff(glob_flags, CNTD_CMD) && msg_cnt) {
  468. X            move(curlin, 0);
  469. X            printw("%-.*s", COLS-1, compose_hdr(current_msg));
  470. X            }
  471. X        } else {
  472. X        print("No messages saved.");
  473. X        if (ison(glob_flags, CNTD_CMD))
  474. X            putchar('\n');
  475. X        }
  476. X    }
  477. X
  478. X    /* preserve message */
  479. X    when C_PRESERVE :
  480. X        if (!msg_cnt) {
  481. X        print("No messages.");
  482. X        if (ison(glob_flags, CNTD_CMD))
  483. X            putchar('\n');
  484. X        break;
  485. X        }
  486. X        if (ison(msg[current_msg].m_flags, PRESERVE))
  487. X        turnoff(msg[current_msg].m_flags, PRESERVE);
  488. X        else
  489. X        turnon(msg[current_msg].m_flags, PRESERVE);
  490. X        turnon(glob_flags, DO_UPDATE);
  491. X        if (ison(glob_flags, CNTD_CMD)) {
  492. X        wprint("%-.*s\n", COLS-1, compose_hdr(current_msg));
  493. X        redo = 1;
  494. X        } else {
  495. X        move(curlin, 0);
  496. X        printw("%-.*s", COLS-1, compose_hdr(current_msg));
  497. X        }
  498. X
  499. X    /* order messages (sort) and redisplay the headers */
  500. X    when C_SORT : case C_REV_SORT :
  501. X        (void) strcpy(file, "sort");
  502. X        if (c == C_REV_SORT) {
  503. X        print("Reverse "), turnon(glob_flags, CONT_PRNT);
  504. X        (void) strcat(file, " -");
  505. X        }
  506. X        print(
  507. X        "Order messages by [author, date, length, Status, subject]: "
  508. X        );
  509. X        if ((c = m_getchar()) == 'a' || c == 'd' || c == 'l' ||
  510. X            c == 'S' || c == 's' || c == 'R') {
  511. X        print("reordering messages...");
  512. X        (void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list);
  513. X        print_more("done.");
  514. X        if (ison(glob_flags, CNTD_CMD))
  515. X            putchar('\n'), puts(compose_hdr(current_msg));
  516. X        redo = 1;
  517. X        } else
  518. X        clr_bot_line();
  519. X
  520. X    when C_QUIT_HARD :
  521. X        (void) mush_quit(0, DUBL_NULL);
  522. X        redo = 1; /* new mail must have come in */
  523. X
  524. X    /* quit or update -- vrfy_update (returns 1 if updated) */
  525. X    when C_QUIT : case C_UPDATE : {
  526. X        clr_bot_line();
  527. X        redo = (c == C_UPDATE);
  528. X        if (!vrfy_update(&redo))
  529. X        if (c == C_UPDATE)
  530. X            break;
  531. X        if (isoff(glob_flags, CNTD_CMD))
  532. X        (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1),
  533. X                msg_list);
  534. X    }
  535. X
  536. X    when C_EXIT : case C_EXIT_HARD :
  537. X        clr_bot_line();
  538. X        iscurses = FALSE;
  539. X        if (c != C_EXIT && c != C_EXIT_HARD)
  540. X        putchar('\n');
  541. X        cleanup(0);
  542. X
  543. X    /* change to a new folder */
  544. X    when C_FOLDER :
  545. X        for (;;) {
  546. X        SIGRET (*oldint)(), (*oldquit)();
  547. X        on_intr();
  548. X        print("New folder (?=list): ");
  549. X        c = Getstr(file, COLS-22, 0);
  550. X        off_intr();
  551. X        if (c > 0) {
  552. X            if (!strcmp(file, "?")) {
  553. X            clr_bot_line();
  554. X            iscurses = 0;
  555. X            puts("folders in your folder directory:");
  556. X            (void) cmd_line(strcpy(buf, "\\folders"), msg_list);
  557. X    puts("Precede folder names with a +. `%' to specify system mailbox.");
  558. X            turnon(glob_flags, CNTD_CMD), iscurses = 1;
  559. X            continue;
  560. X            }
  561. X            clearok(stdscr, FALSE);
  562. X            /* if vrfy_update doesn't verify, but folder command fails,
  563. X             * then we need to reset the updatability of current folder
  564. X             */
  565. X            c = (ison(glob_flags, DO_UPDATE))? TRUE : FALSE;
  566. X            if (strcmp(file, "-?")) {
  567. X            redo = 1; /* so vrfy_update() won't quit */
  568. X            (void) vrfy_update(&redo);
  569. X            }
  570. X            move(LINES-1, 0), refresh();
  571. X            if (cmd_line(sprintf(buf, "folder ! -N %s", file),
  572. X                 msg_list) == -1) {
  573. X            if (c) /* remember state of updatability of folder */
  574. X                turnon(glob_flags, DO_UPDATE);
  575. X            if (ison(glob_flags, CNTD_CMD))
  576. X                putchar('\n');
  577. X            } else
  578. X            redo = 1, turnoff(glob_flags, CNTD_CMD);
  579. X            break;
  580. X        } else {
  581. X            print("\"%s\" unchanged.", mailfile);
  582. X            if (ison(glob_flags, CNTD_CMD))
  583. X            putchar('\n');
  584. X            break;
  585. X        }
  586. X        }
  587. X
  588. X    /* shell escape */
  589. X    when C_SHELL_ESC :
  590. X        print("Shell command: ");
  591. X        if (Getstr(file, COLS-24, 0) < 0)
  592. X        clr_bot_line();
  593. X        else {
  594. X        putchar('\n');
  595. X        iscurses = FALSE;
  596. X        (void) cmd_line(sprintf(buf, "sh %s", file), msg_list);
  597. X        iscurses = TRUE;
  598. X        turnon(glob_flags, CNTD_CMD);
  599. X        }
  600. X
  601. X    /* do a line-mode like command */
  602. X    when C_CURSES_ESC :
  603. X        print(":");
  604. X        if (Getstr(buf, COLS-2, 0) < 0)
  605. X        break;
  606. X        putchar('\n');
  607. X        iscurses = FALSE;
  608. X        if (!*buf) {
  609. X        /* return -1 because iscurses = 0 is not enough! */
  610. X        redo = 0;
  611. X        endwin(); /* this turns echoing back on! */
  612. X        echo_off();
  613. X        return -1;
  614. X        }
  615. X        /* The "source" and "curses" commands need some indication
  616. X         * that we are in curses mode, so use the PRE_CURSES flag.
  617. X         */
  618. X        turnon(glob_flags, PRE_CURSES);
  619. X        (void) cmd_line(buf, msg_list);
  620. X        /* they may have affected message status or had text output */
  621. X        turnon(glob_flags, CNTD_CMD), redo = 1;
  622. X        turnoff(glob_flags, PRE_CURSES);
  623. X        iscurses = TRUE;
  624. X        if (msg_cnt)
  625. X        puts(compose_hdr(current_msg));
  626. X
  627. X    /* send message to printer, redo to display 'p' status */
  628. X    when C_PRINT_MSG : redo = (lpr(0, DUBL_NULL, msg_list) == 0);
  629. X
  630. X    /* cd */
  631. X    when C_CHDIR :
  632. X        print("chdir to [~]: ");
  633. X        if (Getstr(file, COLS-12, 0) < 0)
  634. X        break;
  635. X        clr_bot_line();
  636. X        (void) cmd_line(sprintf(buf, "cd %s", file), msg_list);
  637. X        if (ison(glob_flags, CNTD_CMD))
  638. X        putchar('\n');
  639. X
  640. X    /* variable settings */
  641. X    when C_VAR_SET : case C_IGNORE : case C_ALIAS : case C_OWN_HDR :
  642. X        curs_vars(c); /* CNTD_CMD is reset if there's output! */
  643. X
  644. X    when C_VERSION :
  645. X        (void) do_version();
  646. X        if (ison(glob_flags, CNTD_CMD))
  647. X        putchar('\n');
  648. X
  649. X    when C_MAIL_FLAGS :
  650. X        print("flags [-?]: ");
  651. X        if ((c = Getstr(file, COLS-12, 0)) < 0)
  652. X        break;
  653. X        putchar('\n');
  654. X        if (c == 0)
  655. X        (void) strcpy(file, "-?");
  656. X        else
  657. X        redo = 1; /* In case of -f flag, to display the 'f' status */
  658. X    /* Fall thru */
  659. X    case C_MAIL : {
  660. X        u_long flgs = glob_flags;
  661. X        turnon(glob_flags, IGN_BANG);
  662. X        clr_bot_line();
  663. X        iscurses = FALSE;
  664. X        (void) cmd_line(sprintf(buf, "mail %s", file), msg_list);
  665. X        glob_flags = flgs;
  666. X        iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
  667. X        if (msg_cnt)
  668. X        print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
  669. X    }
  670. X
  671. X    /* reply to mail */
  672. X    when C_REPLY_SENDER : case C_REPLY_ALL : {
  673. X        register char *p = (c == C_REPLY_ALL)? "replyall" : "replysender";
  674. X        clr_bot_line();
  675. X        iscurses = FALSE;
  676. X        if (isoff(msg[current_msg].m_flags, REPLIED))
  677. X        redo = 1;
  678. X        (void) cmd_line(sprintf(buf, "%s %d", p, current_msg+1),
  679. X        msg_list);
  680. X        if (msg_cnt)
  681. X        puts(compose_hdr(current_msg));
  682. X        iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
  683. X    }
  684. X
  685. X    /* type out a message */
  686. X    when C_DISPLAY_MSG : case C_TOP_MSG : case C_DISPLAY_NEXT :
  687. X        if (!msg_cnt ||
  688. X        c != C_DISPLAY_NEXT && ison(msg[current_msg].m_flags, DELETE)) {
  689. X        if (!msg_cnt)
  690. X            print("No messages.");
  691. X        else
  692. X            print("Message %d deleted; type 'u' to undelete.",
  693. X                      current_msg+1);
  694. X        if (ison(glob_flags, CNTD_CMD))
  695. X            putchar('\n');
  696. X        break;
  697. X        }
  698. X        clr_bot_line();
  699. X        iscurses = FALSE;
  700. X        if (ison(glob_flags, CNTD_CMD))
  701. X        putchar('\n');
  702. X        if (c == C_DISPLAY_MSG)
  703. X        c = cmd_line(strcpy(buf, "type"), msg_list);
  704. X        else if (c == C_TOP_MSG)
  705. X        c = cmd_line(strcpy(buf, "top"), msg_list);
  706. X        else {
  707. X        /* "next" screws up the screen whether it displays or not */
  708. X        (void) cmd_line(strcpy(buf, "next"), msg_list);
  709. X        c = 0;
  710. X        }
  711. X        if (c > -1)
  712. X        turnon(glob_flags, CNTD_CMD), redo = 1;
  713. X        iscurses = TRUE;
  714. X        puts(compose_hdr(current_msg));
  715. X
  716. X    /* bind a key or string to a curses-mode command */
  717. X    when C_BIND :  case C_UNBIND : case C_MAP : case C_BIND_MACRO :
  718. X    case C_MAP_BANG : {
  719. X        char *argv[2];
  720. X        argv[0] = (c == C_BIND) ? "bind" :
  721. X              (c == C_UNBIND) ? "unbind" :
  722. X              (c == C_MAP) ? "map" :
  723. X              (c == C_MAP_BANG) ? "map!" : "bind-macro";
  724. X        argv[1] = NULL;
  725. X        if (bind_it(1, argv) < -1)
  726. X        turnon(glob_flags, CNTD_CMD);
  727. X        else if (ison(glob_flags, CNTD_CMD)) /* if it was set anyway */
  728. X        putchar('\n');
  729. X        else
  730. X        (void) curses_help_msg(TRUE);
  731. X    }
  732. X
  733. X    when C_MACRO : 
  734. X        turnon(glob_flags, IN_MACRO);
  735. X        /* Current macro should already be in the mac_stack, so
  736. X         * all we have to do here is look for the next character
  737. X         */
  738. X
  739. X    /* help stuff */
  740. X    when C_HELP :
  741. X        move(LINES-1, 0), refresh();
  742. X        (void) help(0, "curses", cmd_help);
  743. X        turnon(glob_flags, CNTD_CMD);
  744. X        if (msg_cnt)
  745. X        puts(compose_hdr(current_msg));
  746. X
  747. X    otherwise :
  748. X        mac_flush();
  749. X        bell();
  750. X        if (ison(glob_flags, CNTD_CMD)) {
  751. X        /* use print instead of puts to overwrite hit_return msg */
  752. X        print("unknown command"), putchar('\n');
  753. X        redo = 1;
  754. X        }
  755. X    }
  756. X
  757. X    if (ison(glob_flags, CNTD_CMD)) {
  758. X    int old_cnt = msg_cnt;
  759. X    if (!(c = hit_return()) && !redo && msg_cnt == old_cnt)
  760. X        redraw();
  761. X    clr_bot_line();
  762. X    if (old_cnt !=  msg_cnt)
  763. X        redo = 1;
  764. X    if (c)
  765. X        return c;
  766. X    }
  767. X    if (redo) {
  768. X    set_screen_size(); /* it may have changed */
  769. X    n = current_msg;
  770. X    clear();
  771. X    if (/* msg_cnt < screen || */ n_array[0] < n && n < n_array[screen-1])
  772. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  773. X    else
  774. X        (void) cmd_line(sprintf(buf, "\\headers %d", n+1), msg_list);
  775. X    (void) curses_help_msg(TRUE);
  776. X    redo = 0;
  777. X    }
  778. X    return 0;
  779. X}
  780. X
  781. Xvrfy_update(redo)
  782. Xint *redo;
  783. X{
  784. X    char buf[16];
  785. X    int c;
  786. X
  787. X    /* update current folder */
  788. X    if (ison(glob_flags, DO_UPDATE)) {
  789. X    if (ison(glob_flags, READ_ONLY)) {
  790. X        mac_flush();
  791. X        print("Folder is read-only.");
  792. X        if (ison(glob_flags, CNTD_CMD))
  793. X        putchar('\n');
  794. X        return 0;
  795. X    }
  796. X    print("Update folder [y]? ");
  797. X    if ((c = getchar()) != 'y' && c != 'Y' && c != '\n' && !isspace(c)) {
  798. X        print("Folder unchanged.");
  799. X        if (ison(glob_flags, CNTD_CMD))
  800. X        putchar('\n');
  801. X        return 0;
  802. X    }
  803. X    } else if (*redo)
  804. X    return 1;
  805. X    if (cmd_line(strcpy(buf, *redo? "update" : "quit"), msg_list) != -1
  806. X        && ison(glob_flags, CNTD_CMD))
  807. X    *redo = 1, turnoff(glob_flags, CNTD_CMD);
  808. X    turnoff(glob_flags, DO_UPDATE);
  809. X    return 1; /* make sure bottom line is clear and no reverse video */
  810. X}
  811. X
  812. Xscrn_line(line, buf)
  813. Xchar *buf;
  814. X{
  815. X#ifndef A_CHARTEXT
  816. X    (void) strncpy(buf, stdscr->_y[line], COLS-1);
  817. X    buf[COLS-1] = 0; /* strncpy does not null terminate */
  818. X#else
  819. X    int n;
  820. X
  821. X    for (n = 0; n < COLS; n++)
  822. X    if ((buf[n] = (mvinch(line, n) & A_CHARTEXT)) == '\0')
  823. X        break;
  824. X    buf[n] = '\0';
  825. X#endif /* A_CHARTEXT */
  826. X}
  827. X
  828. X/*
  829. X * Generate the help message from the variable curses_help.
  830. X *  If visible is true, the message is displayed,
  831. X *  otherwise its size (in lines) is computed and returned.
  832. X */
  833. Xcurses_help_msg(visible)
  834. Xint visible;
  835. X{
  836. X    int count, i, len, siz = 0, mxm = 0;
  837. X    static int old_siz = 0;
  838. X    register struct cmd_map *list;
  839. X    extern struct cmd_map map_func_names[];
  840. X    char *curs_help = do_set(set_options, "curses_help"), **format;
  841. X
  842. X    if (!curs_help) {
  843. X    if (old_siz && visible) {
  844. X        int bot = min(n_array[screen-1], msg_cnt-1);
  845. X        move(max(0, bot - n_array[0]) + 2, 0), clrtobot();
  846. X        old_siz = 0;
  847. X    }
  848. X    return 0;
  849. X    } else if (!*curs_help)
  850. X    curs_help = DEF_CURSES_HELP;
  851. X    /* Split the help string into words */
  852. X    if (!(format = mk_argv(curs_help, &count, FALSE)) || count <= 0)
  853. X    return 0;
  854. X    /* Generate a help message for each word */
  855. X    for (i = 0; i < count; i++) {
  856. X    char buf[MAX_BIND_LEN*2+MAX_LONG_CMD+5], asc[MAX_BIND_LEN*2];
  857. X
  858. X    buf[0] = '\0'; /* default to empty in case of no match */
  859. X    for (list = cmd_map; list; list = list->m_next) {
  860. X        if (!strcmp(format[i], map_func_names[list->m_cmd].m_str)) {
  861. X        len = strlen(sprintf(buf, "(%s) %s  ",
  862. X                ctrl_strcpy(asc, list->m_str, FALSE),
  863. X                map_func_names[list->m_cmd].m_str));
  864. X        if (len > mxm)
  865. X            mxm = len;
  866. X        break;
  867. X        }
  868. X    }
  869. X    strdup(format[i], buf); /* replace word with its "definition" */
  870. X    }
  871. X    /* Columnate the output nicely */
  872. X    if (mxm > 0) {
  873. X    len = (COLS - 1) / mxm;
  874. X    if (len == 0) {
  875. X        if (visible)
  876. X        print("Curses help message too long!");
  877. X        return 0;
  878. X    }
  879. X    siz = count / len;
  880. X    if (count % len)
  881. X        siz++;
  882. X    if (siz > LINES / 3) {
  883. X        if (visible)
  884. X        print("Curses help message too long!");
  885. X        return 0;
  886. X    }
  887. X    if (visible) {
  888. X        int next = LINES - 1 - siz;
  889. X        if (old_siz > siz) {
  890. X        int bot = min(n_array[screen-1], msg_cnt-1);
  891. X        move(max(0, bot - n_array[0]) + 2, 0), clrtobot();
  892. X        }
  893. X        old_siz = siz;
  894. X        for (i = 0; i < count; i++) {
  895. X        if (!(i % len))
  896. X            move(next, 0), clrtoeol(), ++next;
  897. X        if (format[i][0])
  898. X            printw("%-*.*s", mxm, mxm, format[i]);
  899. X        }
  900. X        refresh();
  901. X    }
  902. X    }
  903. X    free_vec(format);
  904. X    return siz;
  905. X}
  906. X
  907. Xset_screen_size()
  908. X{
  909. X    int hlp_siz = LINES - 2 - curses_help_msg(FALSE); 
  910. X
  911. X    if (!do_set(set_options, "screen"))
  912. X#ifdef USG
  913. X    switch (_tty.sg_ospeed & CBAUD)
  914. X#else /* USG */
  915. X    switch (_tty.sg_ospeed)
  916. X#endif /* USG */
  917. X    {
  918. X        case B300 :  screen = min(hlp_siz, 7);
  919. X        when B1200 : screen = min(hlp_siz, 14);
  920. X        when B2400 : screen = min(hlp_siz, 22);
  921. X        otherwise :  screen = hlp_siz;
  922. X    }
  923. X    else
  924. X    screen = min(screen, hlp_siz);
  925. X}
  926. X
  927. X/*
  928. X * prompt for a carriage return, but return whatever user types unless
  929. X * it's a character which he might regret (like 'q' or 'x'). Ignore
  930. X * interrupts (kind of) because we have nowhere to longjmp to.  When we
  931. X * return, we'll setjmp again (top of loop.c)
  932. X */
  933. Xhit_return()
  934. X{
  935. X    int c;
  936. X
  937. X    turnon(glob_flags, IGN_SIGS);
  938. X    iscurses = FALSE;
  939. X    (void) check_new_mail();
  940. X    iscurses = TRUE;
  941. X    mail_status(1), addstr("...continue... "), refresh();
  942. X    c = getcmd();
  943. X    turnoff(glob_flags, IGN_SIGS);
  944. X
  945. X    /* don't let the user type something he might regret */
  946. X    if (c == C_QUIT || c == C_EXIT)
  947. X    return C_NULL;
  948. X    return c;
  949. X}
  950. X
  951. Xcurses_msg_list(str, list, m_list)
  952. Xregister char *str, *list;
  953. Xchar m_list[];
  954. X{
  955. X    register char *p = NULL;
  956. X    int c, sv_cur_msg = current_msg;
  957. X
  958. X    print(str);
  959. X    c = Getstr(list, COLS-13, 0);
  960. X    move(LINES-1, 0), refresh();
  961. X    if (c <= 0 || !(p = do_range(list, m_list)) ||
  962. X    (p == list && *p && *p != '$' && *p != '^')) {
  963. X    if (p)
  964. X        print("Invalid message list: %s", p);
  965. X    current_msg = sv_cur_msg;
  966. X    return 0;
  967. X    }
  968. X    current_msg = sv_cur_msg;
  969. X    return 1;
  970. X}
  971. X
  972. Xcurs_vars(which)
  973. Xint which;  /* really, a char */
  974. X{
  975. X    char c, buf[128], buf2[128], *string;
  976. X    struct options **list;
  977. X
  978. X    switch(which) {
  979. X    case C_OWN_HDR : string = "my_hdr", list = &own_hdrs;
  980. X    when C_ALIAS : string = "alias", list = &aliases;
  981. X    when C_IGNORE : string = "ignore", list = &ignore_hdr;
  982. X    when C_VAR_SET : string = "set", list = &set_options;
  983. X    otherwise : clr_bot_line(); return;
  984. X    }
  985. X
  986. X    print("%s [? Set Unset All]: ", string);
  987. X    c = m_getchar();
  988. X    clr_bot_line();
  989. X    switch (Lower(c)) {
  990. X    /* if help, print help -- if "all", show all settings. */
  991. X    case '?' : case 'a' :
  992. X        if (c == '?') {
  993. X        if (!strcmp(string, "set")) {
  994. X            print("which variable? [all <var>]: ");
  995. X            if ((c = Getstr(buf+1, COLS-40, 0)) < 0)
  996. X            return;
  997. X            clr_bot_line();
  998. X            buf[0] = '?';
  999. X            if (c > 0) {
  1000. X            char *argv[3];
  1001. X            argv[0] = string;
  1002. X            argv[1] = buf;
  1003. X            argv[2] = NULL;
  1004. X            Lower(buf[1]);
  1005. X            if (!strcmp(buf+1, "a"))
  1006. X                (void) strcpy(buf+1, "all");
  1007. X            if (!strcmp(buf+1, "all"))
  1008. X                turnon(glob_flags, CNTD_CMD);
  1009. X            (void) set(2, argv, (char *) 0);
  1010. X            break;
  1011. X            }
  1012. X        }
  1013. X        /* help returns next command (hit_return) */
  1014. X        (void) help(0, string, cmd_help);
  1015. X        turnon(glob_flags, CNTD_CMD);
  1016. X        return;
  1017. X        }
  1018. X        turnon(glob_flags, CNTD_CMD);
  1019. X        (void) do_set(*list, NULL);
  1020. X
  1021. X    /* if set, prompt for string and let user type */
  1022. X    when 's' :
  1023. X        print("set: ");
  1024. X        c = Getstr(buf, COLS-18, 0);
  1025. X        clr_bot_line();
  1026. X        if (c > 0)
  1027. X        (void) cmd_line(sprintf(buf2, "%s %s", string, buf), msg_list);
  1028. X
  1029. X    /* if unset, just as easy as set! */
  1030. X    when 'u' :
  1031. X        print("unset: ", string);
  1032. X        if (Getstr(buf, COLS-18, 0) > 0 && !un_set(list, buf))
  1033. X        print("%s isn't set", buf);
  1034. X    }
  1035. X    if (ison(glob_flags, CNTD_CMD))
  1036. X    putchar('\n');
  1037. X    else
  1038. X    (void) curses_help_msg(TRUE);
  1039. X}
  1040. X#endif /* CURSES */
  1041. END_OF_FILE
  1042. if test 28433 -ne `wc -c <'mush/curses.c'`; then
  1043.     echo shar: \"'mush/curses.c'\" unpacked with wrong size!
  1044. fi
  1045. # end of 'mush/curses.c'
  1046. fi
  1047. if test -f 'mush/mush.h' -a "${1}" != "-c" ; then 
  1048.   echo shar: Will not clobber existing file \"'mush/mush.h'\"
  1049. else
  1050. echo shar: Extracting \"'mush/mush.h'\" \(22786 characters\)
  1051. sed "s/^X//" >'mush/mush.h' <<'END_OF_FILE'
  1052. X/* @(#)mush.h    (c) copyright 1986 (Dan Heller) */
  1053. X
  1054. X#include "config.h"
  1055. X
  1056. X#ifdef CURSES
  1057. X
  1058. X#ifdef USG
  1059. X#    define _USG
  1060. X#    undef USG
  1061. X#endif /* USG */
  1062. X#ifdef SYSV
  1063. X#    define _SYSV
  1064. X#    undef SYSV
  1065. X#endif /* SYSV */
  1066. X#include <curses.h>
  1067. X#if !defined(USG) && defined(_USG)
  1068. X#    define USG
  1069. X#endif /* USG */
  1070. X#if !defined(SYSV) && defined(_SYSV)
  1071. X#    define SYSV
  1072. X#endif /* SYSV */
  1073. X
  1074. X#else /* CURSES */
  1075. X#include <stdio.h>
  1076. X#if defined(SYSV) && defined(USG)
  1077. X#include <termio.h>
  1078. X#endif /* SYSV && USG */
  1079. X#endif /* CURSES */
  1080. X
  1081. X#include <ctype.h>
  1082. X#include <errno.h>
  1083. X#include <setjmp.h>
  1084. X#include "strings.h"
  1085. X
  1086. X#ifdef BSD
  1087. X#define fputs Fputs    /* See comments in print.c */
  1088. X#endif /* BSD */
  1089. X
  1090. Xextern char
  1091. X    *malloc(),        /* allocate memory */
  1092. X    *calloc(),        /* allocate and clear memory */
  1093. X    *realloc();        /* re-allocate memory */
  1094. X
  1095. Xextern void
  1096. X    free_vec(),        /* free a malloc'ed argv */
  1097. X    xfree();        /* free malloc'ed pointers */
  1098. X
  1099. X#if defined(SUNTOOL) || defined(SUN_3_5) || defined(SUN_4_0) || defined(SUN_4_1)
  1100. X#if !defined(BSD) && !defined(SYSV)
  1101. X#    define BSD /* default to BSD */
  1102. X#endif /* !BSD && !SYSV */
  1103. X#if !defined(SUN_3_5) && !defined(SUN_4_0)
  1104. X#    define SUN_4_0 /* default to sun 4.0 */
  1105. X#endif /* !SUN_3_5 && !SUN_4_0 */
  1106. X#ifdef SUN_4_0
  1107. X#    undef SUN_3_5
  1108. X#    undef SIGRET
  1109. X#    define SIGRET void
  1110. X#endif /* SUN_4_0 */
  1111. X#endif /* SUNTOOL || SUN_3_5 || SUN_4_0 */
  1112. X
  1113. X#ifdef SUNTOOL
  1114. X#    include <suntool/sunview.h>
  1115. X#ifdef SUN_4_0
  1116. X#    include <suntool/alert.h>
  1117. X#endif /* SUN_4_0 */
  1118. X#    include <suntool/textsw.h>
  1119. X#    include <sys/ioctl.h>   /* for ltchars */
  1120. X#else
  1121. X#    include <sys/types.h>
  1122. X#    include <signal.h>
  1123. X#    ifndef SYSV
  1124. X#    include <sys/time.h>
  1125. X#    include <sys/ioctl.h>   /* for ltchars */
  1126. X#    else
  1127. X#    include <time.h>
  1128. X#    include <fcntl.h>
  1129. X#    endif /* SYSV */
  1130. X#endif /* SUNTOOL */
  1131. X
  1132. X#include <sys/stat.h>
  1133. X#include <sys/file.h>
  1134. X
  1135. X#ifdef SUNTOOL
  1136. X#    include <suntool/panel.h>
  1137. X#    include <suntool/canvas.h>
  1138. X#    include <suntool/tty.h>
  1139. X#    include <suntool/menu.h>
  1140. X#    include <suntool/icon.h>
  1141. X#    include <suntool/scrollbar.h>
  1142. X#    include <suntool/icon_load.h>
  1143. X#endif /* SUNTOOL */
  1144. X
  1145. X/* if no maximum number of files can be found, we'll use getdtablesize() */
  1146. X#ifdef _NFILE
  1147. X#    define MAXFILES _NFILE
  1148. X#else
  1149. X#ifdef NOFILE
  1150. X#    define MAXFILES NOFILE
  1151. X#endif /* NOFILE */
  1152. X#endif /* _NFILE */
  1153. X
  1154. X#ifndef MAXPATHLEN
  1155. X#define MAXPATHLEN BUFSIZ
  1156. X#endif /* MAXPATHLEN */
  1157. X
  1158. X#ifdef CTRL
  1159. X#undef CTRL
  1160. X#endif /* CTRL */
  1161. X#define CTRL(c)        ((c) & 037)
  1162. X
  1163. X#define ESC         '\033'
  1164. X
  1165. X#define NO_STRING    ""
  1166. X#ifdef  NULL
  1167. X#undef  NULL
  1168. X#endif /* NULL */
  1169. X#define NULL        (char *)0
  1170. X#define NULL_FILE    (FILE *)0
  1171. X#define DUBL_NULL    (char **)0
  1172. X#define TRPL_NULL    (char ***)0
  1173. X#ifdef putchar
  1174. X#undef putchar
  1175. X#endif /* putchar */
  1176. X#define putchar(c)    (void) (fputc(c, stdout), fflush(stdout))
  1177. X#ifdef SUNTOOL
  1178. Xextern int bell();
  1179. X#else /* SUNTOOL */
  1180. X#define bell()        (void) (fputc('\007', stderr), fflush(stderr))
  1181. X#endif /* SUNTOOL */
  1182. X
  1183. X/* For error recovery purposes, send keyboard generated signals to a special
  1184. X * routine (interrupt) to set a global flag (WAS_INTR) and return to the
  1185. X * calling routine which is responsible for checking the flag.  For both
  1186. X * on_intr() and off_intr() macros, initialize WAS_INTR to false.
  1187. X */
  1188. X#define on_intr() \
  1189. X    turnoff(glob_flags, WAS_INTR), oldint = signal(SIGINT, intrpt), \
  1190. X    oldquit = signal(SIGQUIT, intrpt)
  1191. X
  1192. X#define off_intr() \
  1193. X    (void) (turnoff(glob_flags, WAS_INTR), signal(SIGINT, oldint), \
  1194. X        signal(SIGQUIT, oldquit))
  1195. X
  1196. X/* Don't flush input when setting echo or cbreak modes (allow typeahead) */
  1197. X#ifdef TIOCSETN
  1198. X#ifdef stty
  1199. X#undef stty
  1200. X#endif /* stty */
  1201. X#define stty(fd, sgttybuf)    ioctl(fd, TIOCSETN, sgttybuf)
  1202. X#endif /* TIOCSETN */
  1203. X
  1204. X/* for system-V machines that run termio */
  1205. X#if defined(SYSV) && defined(USG)
  1206. Xunsigned char vmin, vtime;
  1207. X#define sg_erase  c_cc[2]
  1208. X#define sg_flags  c_lflag
  1209. X#define sg_kill   c_cc[3]
  1210. X#define sg_ospeed c_cflag
  1211. X#define gtty(fd, SGTTYbuf)    ioctl(fd, TCGETA, SGTTYbuf)
  1212. X#undef stty
  1213. X#define stty(fd, SGTTYbuf)    ioctl(fd, TCSETAW, SGTTYbuf)
  1214. X#define echon()    (_tty.sg_flags |= (ECHO|ECHOE),    stty(0, &_tty))
  1215. X#define echoff()   (_tty.sg_flags &= ~ECHO,   stty(0, &_tty))
  1216. X#define cbrkon()   \
  1217. X    (_tty.sg_flags &= ~ICANON, _tty.c_cc[VMIN] = 1, stty(0, &_tty))
  1218. X#define cbrkoff()  \
  1219. X    (_tty.sg_flags |= ICANON,_tty.c_cc[VMIN] = vmin,_tty.c_iflag |= ICRNL, \
  1220. X        _tty.c_cc[VTIME] = vtime, stty(0, &_tty))
  1221. X#define savetty()  \
  1222. X    (void) gtty(0, &_tty), vtime = _tty.c_cc[VTIME], vmin = _tty.c_cc[VMIN]
  1223. X#define cbreak()   cbrkon()
  1224. X#define nocbreak() cbrkoff()
  1225. X
  1226. X/* If curses isn't defined, declare our 'tty' and macros for echo/cbreak */
  1227. X#ifndef CURSES
  1228. Xtypedef struct termio SGTTY;
  1229. X#define echom()    echon()
  1230. X#define noechom()  echoff()
  1231. X#define crmode()   cbrkon()
  1232. X#define nocrmode() cbrkoff()
  1233. X
  1234. X#else /* CURSES */
  1235. X/* If curses is defined, use the echo/cbreak commands in library only
  1236. X * if curses is running.  If curses isn't running, use macros above.
  1237. X */
  1238. X#define echom()    ((iscurses) ? echo(): echon())
  1239. X#define noechom()  ((iscurses) ? noecho(): echoff())
  1240. X#define crmode()   ((iscurses) ? cbreak() : cbrkon())
  1241. X#define nocrmode() ((iscurses) ? nocbreak() : cbrkoff())
  1242. X#endif /* CURSES */
  1243. X#endif /* SYSV && USG */
  1244. X
  1245. X#if !defined(USG)
  1246. X#ifndef CURSES
  1247. X/* if curses is not defined, simulate the same tty based macros */
  1248. Xtypedef struct sgttyb SGTTY;
  1249. X/* Do real ioctl calls to set the tty modes */
  1250. X#define crmode()   (_tty.sg_flags |= CBREAK,  stty(0, &_tty))
  1251. X#define nocrmode() (_tty.sg_flags &= ~CBREAK, stty(0, &_tty))
  1252. X#define echom()    (_tty.sg_flags |= ECHO,    stty(0, &_tty))
  1253. X#define noechom()  (_tty.sg_flags &= ~ECHO,   stty(0, &_tty))
  1254. X#define savetty()  (void) gtty(0, &_tty)
  1255. X#else /* CURSES */
  1256. X#define echom()    echo()
  1257. X#define noechom()  noecho()
  1258. X#endif /* ~CURSES */
  1259. X#endif /* ~USG */
  1260. X
  1261. X/* With all that out of the way, we can now declare our tty type */
  1262. XSGTTY _tty;
  1263. X
  1264. Xextern char
  1265. X    del_line,        /* tty delete line character */
  1266. X    del_word,        /* tty delete word character */
  1267. X    del_char,        /* backspace */
  1268. X    reprint_line,    /* usually ^R */
  1269. X    eofc,        /* usually ^D */
  1270. X    lit_next,        /* usually ^V */
  1271. X    complete,        /* word completion, usually ESC */
  1272. X    complist;        /* completion listing, usually tab */
  1273. X
  1274. X/* These macros now turn on/off echo/cbreak independent of the UNIX running */
  1275. X#define echo_on()    \
  1276. X    if (_tty.sg_flags && isoff(glob_flags, ECHO_FLAG)) nocrmode(), echom()
  1277. X#define echo_off()    \
  1278. X    if (_tty.sg_flags && isoff(glob_flags, ECHO_FLAG)) crmode(), noechom()
  1279. X
  1280. X#define strdup(dst, src) (xfree (dst), dst = savestr(src))
  1281. X#define Debug        if (debug == 0) {;} else (void) wprint
  1282. X
  1283. X#ifdef SYSV
  1284. X#ifndef L_SET
  1285. X#define L_SET    0
  1286. X#endif /* L_SET */
  1287. X#ifndef F_OK
  1288. X#define F_OK    000
  1289. X#define R_OK    004
  1290. X#define W_OK    002
  1291. X#define E_OK    001
  1292. X#endif /* F_OK */
  1293. X#ifdef u_long
  1294. X#undef u_long
  1295. X#endif /* u_long */
  1296. X#define u_long    unsigned long
  1297. X#ifndef HPUX
  1298. X#define vfork   fork
  1299. X#endif /* HPUX */
  1300. X#ifndef SIGCHLD
  1301. X#define SIGCHLD SIGCLD
  1302. X#endif /* SIGCHLD */
  1303. X#endif /* SYSV */
  1304. X
  1305. X#if !defined(SUNTOOL) && !defined(CURSES)
  1306. X
  1307. X#define TRUE          1
  1308. X#define FALSE          0
  1309. X#define print          (void) printf
  1310. X#define wprint          (void) printf
  1311. X#define print_more      (void) printf
  1312. X
  1313. X#endif /* !SUNTOOL && !CURSES */
  1314. X
  1315. X#ifndef max
  1316. X#define max(a,b) (((a) > (b)) ? (a) : (b))
  1317. X#define min(a,b) (((a) < (b)) ? (a) : (b))
  1318. X#endif /* max */
  1319. X
  1320. X#if defined(CURSES) && (!defined(SUNTOOL))
  1321. X#define wprint    (void) printf
  1322. X#endif /* CURSES && (!SUNTOOL) */
  1323. X
  1324. X#ifdef SUNTOOL
  1325. X/* stdout may be closed */
  1326. X#define printf wprint
  1327. X#endif /* SUNTOOL */
  1328. X
  1329. X#if defined(CURSES) || defined(SUNTOOL)
  1330. X#define print_more      turnon(glob_flags, CONT_PRNT), print
  1331. Xvoid print();    /* printf to window or curses or tty accordingly */
  1332. X#endif /* CURSES || SUNTOOL */
  1333. X
  1334. X#define ArraySize(o)      (sizeof(o) / sizeof(*o))
  1335. X
  1336. X#ifdef SUNTOOL
  1337. X
  1338. X#define NO_ITEM        (Panel_item)0
  1339. X#define NO_EVENT    (struct inputevent *)0
  1340. X#define TIME_OUT    60    /* sleep 60 secs between mailchecks */
  1341. X#define PIX_XOR        PIX_SRC ^ PIX_DST
  1342. X#define ID        event_id(event)
  1343. X#define l_width()    mush_font->pf_defaultsize.x /* width of letter */
  1344. X#define l_height()    mush_font->pf_defaultsize.y /* height of letter */
  1345. X#define Clrtoeol(w,x,y)    ((void) pw_text(w, x, y, PIX_SRC, mush_font, blank))
  1346. X
  1347. X/* Miscellaneous old-SunView cleanup */
  1348. X#ifndef TTY_ARGV_DO_NOT_FORK
  1349. X#define TTY_ARGV_DO_NOT_FORK (-1)
  1350. X#endif
  1351. X
  1352. X#endif /* SUNTOOL */
  1353. X
  1354. X/* bits and pieces */
  1355. X#define turnon(flg,val)   ((flg) |= (u_long)(val))
  1356. X#define turnoff(flg,val)  ((flg) &= ~(u_long)(val))
  1357. X#define ison(flg,val)     ((u_long)(flg) & (u_long)(val))
  1358. X#define isoff(flg,val)    (!ison((flg), (val)))
  1359. X#define set_replied(n)      \
  1360. X    if (isoff(msg[n].m_flags, REPLIED)) \
  1361. X        turnon(glob_flags, DO_UPDATE), turnon(msg[n].m_flags, REPLIED)
  1362. X#define set_isread(n)      \
  1363. X    if (ison(msg[n].m_flags, UNREAD)) \
  1364. X        turnon(glob_flags, DO_UPDATE), turnoff(msg[n].m_flags, UNREAD)
  1365. X
  1366. X#define in_pipe() (ison(glob_flags, DO_PIPE|IS_PIPE))
  1367. X#define in_macro() (ison(glob_flags, LINE_MACRO|IN_MACRO))
  1368. X#define line_macro(s) (void) (turnon(glob_flags, LINE_MACRO), mac_push(s))
  1369. X#define curs_macro(s) (void) (turnon(glob_flags, IN_MACRO), mac_push(s))
  1370. X#define Ungetstr(s) (void) (turnon(glob_flags, QUOTE_MACRO), mac_push(s))
  1371. X
  1372. X/* global conditions */
  1373. X#define is_shell (mailfile && *mailfile)
  1374. X
  1375. X/* msg lists represented by bits (8 should be replaced by sizeof(char) */
  1376. X#define clear_msg_list(list)      ((void) bzero(list, (msg_cnt+7)/8))
  1377. X#define msg_bit(list, n)    ((list[(n) / 8] >> ((n) % 8)) & 1)
  1378. X#define set_msg_bit(list, n)    (list[(n) / 8] |= (1 << ((n) % 8)))
  1379. X#define unset_msg_bit(list, n)  (list[(n) / 8] &= ~(1 << ((n) % 8)))
  1380. X#define bput(S1, S2, Len, op)                   \
  1381. X        do {                         \
  1382. X            register char *s1 = S1, *s2 = S2;         \
  1383. X            register int len = Len;             \
  1384. X            while(len--)                 \
  1385. X            *s2++ op *s1++;             \
  1386. X        } while (0)
  1387. X#define bitput(m1,m2,len,op)    bput(m1, m2, (((len)+7)/8), op)
  1388. X
  1389. X/* convenience and/or readability */
  1390. X#define when          break;case
  1391. X#define otherwise      break;default
  1392. X#define lower(c)      (isupper(c)? tolower(c): c)
  1393. X#define Lower(c)      (c = lower(c))
  1394. X#define upper(c)      (islower(c)? toupper(c): c)
  1395. X#define Upper(c)      (c = upper(c))
  1396. X#define skipspaces(n)     for(p += (n); *p == ' ' || *p == '\t'; ++p)
  1397. X#define skipdigits(n)     for(p += (n); isdigit(*p); ++p)
  1398. X#define ismsgnum(c)       (isdigit(c)||c=='.'||c=='^'||c=='$'||c=='*')
  1399. X#define skipmsglist(n)\
  1400. X    for(p += (n); ismsgnum(*p) || index(" \t,-{`}", *p); ++p)\
  1401. X    if (*p != '`' || !p[1]) {;} else do ++p; while (*p && *p != '`')
  1402. X
  1403. X/* define a macro to declare unsigned-long bits */
  1404. X#define ULBIT(bit)        ((u_long)1 << (u_long)(bit))
  1405. X
  1406. X/* various flags */
  1407. Xu_long   glob_flags;    /* global boolean flags thruout the whole program */
  1408. X#define DO_UPDATE   ULBIT(0) /* folder has been modified -- update it */
  1409. X#define REV_VIDEO   ULBIT(1) /* reverse video for curses or toolmode */
  1410. X#define CONT_PRNT   ULBIT(2) /* continue to print without a '\n' */
  1411. X#define DO_SHELL    ULBIT(3) /* run a shell even if no mail? (true if tool) */
  1412. X#define DO_PIPE     ULBIT(4) /* if commands are piping to other commands */
  1413. X#define IS_PIPE     ULBIT(5) /* true if commands' "input" comes from a pipe */
  1414. X#define IGN_SIGS    ULBIT(6) /* true if catch() should not longjmp */
  1415. X#define IGN_BANG    ULBIT(7) /* ignore ! as a history reference */
  1416. X#define ECHO_FLAG   ULBIT(8) /* if true, echo|cbreak is ON, echo typing (-e) */
  1417. X#define IS_GETTING  ULBIT(9) /* true if we're getting input for a letter */
  1418. X#define PRE_CURSES  ULBIT(10) /* true if curses will run, but hasn't started */
  1419. X#define READ_ONLY   ULBIT(11) /* -r passed to folder() for read only */
  1420. X#define REDIRECT    ULBIT(12) /* true if stdin is being redirected */
  1421. X#define WAS_INTR    ULBIT(13) /* catch interrupts, set this flag (signals.c) */
  1422. X#define WARNING     ULBIT(14) /* if set, various warning messages are printed */
  1423. X#define NEW_MAIL    ULBIT(15) /* new mail has arrived; mush is busy or closed */
  1424. X#define CNTD_CMD    ULBIT(16) /* curses.c -- promotes "...continue..." prompt */
  1425. X#define IS_SENDING  ULBIT(17) /* was run to send mail, not run as a shell */
  1426. X#define MIL_TIME    ULBIT(19) /* if $mil_time is set, use 24hr time fmt */
  1427. X#define DATE_RECV   ULBIT(20) /* $date_received: show date received on msgs */
  1428. X#define IN_MACRO    ULBIT(21) /* input is currently being read from a macro */
  1429. X#define LINE_MACRO  ULBIT(22) /* escape to line mode from curses in progress */
  1430. X#define QUOTE_MACRO ULBIT(23) /* protect current macro from recursive expan.. */
  1431. X#define NEW_FRAME   ULBIT(24) /* toolmode should build a new frame for pager */
  1432. X#define HELP_TEXT   ULBIT(25) /* create textsw frame for paging help messages */
  1433. X
  1434. X/* flags to control composition */
  1435. X#define VERBOSE        ULBIT(0)  /* verbose flag for sendmail */
  1436. X#define INCLUDE        ULBIT(1)  /* include msg in response */
  1437. X#define INCLUDE_H    ULBIT(2)  /* include msg with header */
  1438. X#define EDIT        ULBIT(3)  /* enter editor by default on mailing */
  1439. X#define SIGN        ULBIT(4)  /* auto-include ~/.signature in mail */
  1440. X#define DO_FORTUNE    ULBIT(5)  /* add a fortune at end of msgs */
  1441. X#define EDIT_HDRS    ULBIT(6)  /* user edits headers using editor */
  1442. X#define SEND_NOW    ULBIT(7)  /* send without further changes */
  1443. X#define NO_SIGN        ULBIT(8)  /* override SIGN and DO_FORTUNE */
  1444. X
  1445. X/* msg flags */
  1446. X#define PRINTED        ULBIT(4)  /* sent through lpr command */
  1447. X#define NO_HEADER    ULBIT(6)  /* don't print header of message */
  1448. X#define DELETE        ULBIT(7)
  1449. X#define OLD        ULBIT(8)
  1450. X#define UNREAD        ULBIT(9)
  1451. X#define UPDATE_STATUS    ULBIT(10) /* change status of msg when copyback */
  1452. X#define NO_PAGE        ULBIT(11) /* don't page this message */
  1453. X#define INDENT        ULBIT(12) /* indent included msg with string */
  1454. X#define NO_IGNORE    ULBIT(13) /* don't ignore headers */
  1455. X#define PRESERVE    ULBIT(14) /* preserve in mailbox unless deleted */
  1456. X#define M_TOP        ULBIT(14) /* just print the top of msg (same as pre) */
  1457. X#define FORWARD        ULBIT(15) /* Forward messages into the message buffer */
  1458. X#define REPLIED        ULBIT(16) /* Messages that have been replied to */
  1459. X#define NEW_SUBJECT    ULBIT(17) /* new subject regardless of $ask (mail -s) */
  1460. X#define SAVED        ULBIT(18) /* when message has been saved */
  1461. X#ifdef MSG_SEPARATOR
  1462. X#define NO_SEPARATOR    ULBIT(19) /* don't include message separator lines */
  1463. X#endif /* MSG_SEPARATOR */
  1464. X
  1465. X#define    MAXMSGS_BITS    MAXMSGS/sizeof(char)    /* number of bits for bitmap */
  1466. X
  1467. Xstruct msg {
  1468. X    u_long m_flags;
  1469. X    long   m_offset;    /* offset in tempfile of msg */
  1470. X    long   m_size;    /* number of bytes in msg */
  1471. X    int    m_lines;    /* number of lines in msg */
  1472. X    char   *m_date_recv;/* Date user received msg (see dates.c for fmt) */
  1473. X    char   *m_date_sent;/* Date author sent msg (see dates.c for fmt) */
  1474. X} msg[MAXMSGS];
  1475. X
  1476. Xstruct options {
  1477. X    char *option;
  1478. X    char *value;
  1479. X    struct options *next;
  1480. X} *set_options, *aliases, *ignore_hdr, *functions, *fkeys, *own_hdrs;
  1481. X
  1482. X#define chk_option(v,f)    chk_two_lists(do_set(set_options,(v)), (f), "\t ,")
  1483. X
  1484. Xstruct cmd {
  1485. X    char *command;
  1486. X    int (*func)();
  1487. X};
  1488. Xextern struct cmd ucb_cmds[];
  1489. Xextern struct cmd cmds[], hidden_cmds[];
  1490. X
  1491. XFILE
  1492. X    *tmpf,        /* temporary holding place for all mail */
  1493. X    *mask_fopen(),    /* open a file with umask 077 (permissions 600) */
  1494. X    *open_file(),    /* open a file or program for write/append */
  1495. X    *lock_fopen(),    /* open and lock a file as an atomic operation */
  1496. X    *popen();        /* this should be in stdio.h */
  1497. X
  1498. Xextern char
  1499. X    *sys_errlist[],    /* system's list of global error messages */
  1500. X    **environ;        /* user's environment variables */
  1501. X
  1502. Xextern int errno;    /* global system error number */
  1503. Xjmp_buf jmpbuf;        /* longjmp to jmpbuf on sigs (not in tool) */
  1504. X
  1505. Xchar
  1506. X    debug,        /* debug causes various print statements in code */
  1507. X    tempfile[MAXPATHLEN],    /* path to filename of temporary file */
  1508. X    msg_list[MAXMSGS_BITS],    /* MAXMSGS bits of boolean storage */
  1509. X    **alternates,    /* alternates list --see alts() */
  1510. X    *cmd_help,        /* filename of location for "command -?" commands. */
  1511. X    *login,        /* login name of user */
  1512. X    *mailfile,        /* path to filename of current mailfile */
  1513. X    **ourname,        /* the name and aliases of the current host */
  1514. X    **known_hosts,    /* the names of all hosts connected via uucp */
  1515. X    *prompt,        /* the prompt string -- may have %d */
  1516. X    *format_prompt(),    /* function to format prompts from the prompt string */
  1517. X    *escape,        /* the "tilde escape" when inputting text to letter */
  1518. X    *hdrs_only,        /* true if -H flag was given --set to args */
  1519. X    *hdr_format,    /* set to the header format string; referenced a lot */
  1520. X    *spoolfile,        /* MAILDIR/$USER in a string -- this is used a lot */
  1521. X    *msg_get(),        /* find start of message and return From_ line */
  1522. X    *do_range(),    /* parse a string converting to a "range" of numbers */
  1523. X    *getpath(),        /* static char returning path (expanding ~, +, %, #) */
  1524. X    *getdir(),        /* uses getpath() to expand and test directory names */
  1525. X    *do_set(),        /* set/unset an option, alias, ignored-hdr */
  1526. X    *reverse(),        /* reverse a string */
  1527. X    *trim_filename(),    /* remove or condense leading file name path */
  1528. X    *prog_name,
  1529. X
  1530. X    /* from loop.c */
  1531. X    **make_command(),    /* build a command vector (argv) */
  1532. X    **mk_argv(),    /* given a string, make a vector */
  1533. X    *variable_stuff(),    /* return information about variables */
  1534. X    *check_internal(),    /* test or evaluate internal variables */
  1535. X
  1536. X    /* from dates.c */
  1537. X    *Time(),        /* returns string expression of time (takes args) */
  1538. X    *date_to_ctime(),    /* convert a date into ctime() format */
  1539. X    *date_to_string(),    /* returns a string described by parse_date() */
  1540. X    *msg_date(),    /* return a string of the date of a message */
  1541. X    *parse_date(),    /* parse an ascii date, and return message-id str */
  1542. X    *rfc_date(),    /* create a date string compliant to RFC822 */
  1543. X
  1544. X    /* from hdrs.c */
  1545. X    *cc_to(),         /* when responding, return str which is the cc-list */
  1546. X    *compose_hdr(),    /* passes hdr_format to format_hdr() for displays */
  1547. X    *format_hdr(),    /* returns a formatted line describing passed msg # */
  1548. X    *header_field(),    /* the line in msg described by arg (message header) */
  1549. X    *reply_to(),    /* who do we reply to when responding */
  1550. X    *subject_to(),      /* when responding, return str which is the subject */
  1551. X
  1552. X    /* addrs.c */
  1553. X    *alias_to_address(),/* convert a name[list] to "real" names */
  1554. X    *bang_form(),    /* construct a !-style form of an address */
  1555. X    *get_name_n_addr(), /* get name and addr from a well-formed address */
  1556. X    *set_header(),     /* [interactive] proc to set/display to/subject/cc */
  1557. X    *wrap_addrs();    /* insert newlines in between headers */
  1558. X
  1559. Xint
  1560. X    last_msg_cnt,    /* when checking for new mail, save the last msg_cnt */
  1561. X    msg_cnt,        /* total number of messages */
  1562. X    crt,        /* min number of lines msg contains to invoke pager */
  1563. X    current_msg,    /* the current message we're dealing with */
  1564. X    exec_pid,        /* pid of a command that has been "exec"ed */
  1565. X    hist_no,        /* command's history number */
  1566. X    iscurses,        /* if we're running curses */
  1567. X    istool,        /* argv[0] == "xxxxtool", ranges from 0 to 2 */
  1568. X    n_array[128],    /* array of message numbers in the header window */
  1569. X    screen,        /* number of headers window can handle */
  1570. X    wrapcolumn,        /* compose mode line wrap, measured from left */
  1571. X
  1572. X    close_lock(),     /* unlock and close a file opened by lock_fopen() */
  1573. X
  1574. X    mush_quit(), do_alias(), respond(), cd(), sh(), stop(),
  1575. X    folder(), folders(), merge_folders(), do_undigest(),
  1576. X    save_msg(), delete(), do_mail(), lpr(), alts(), set(), do_hdrs(),
  1577. X    save_opts(), preserve(), sort(), readmsg(), edit_msg(), eval_cmd(),
  1578. X    do_pick(), print_help(), question_mark(), do_from(), my_stty(),
  1579. X    do_version(), disp_hist(), source(), do_echo(), ls(), pipe_msg(),
  1580. X    await(), nopenfiles(), file_to_fp(),
  1581. X    check_new_mail(), get_new_mail(), show_new_mail(),
  1582. X    Setenv(), Unsetenv(), Printenv(), msg_flags(), toggle_debug();
  1583. X
  1584. X#ifndef SIGRET
  1585. X#define SIGRET int
  1586. X#endif /* SIGRET */
  1587. XSIGRET
  1588. X    rm_edfile(),    /* remove letter-compose file on interrupts */
  1589. X    stop_start(),    /* handle job control signals */
  1590. X    bus_n_seg(),    /* handle runtime segfaults -- exit gracefully */
  1591. X    sigchldcatcher(),    /* account for terminated child processes */
  1592. X    catch(),        /* catch user (keyboard) generated signals */
  1593. X    intrpt();        /* handle interrupts when we don't want to */
  1594. X
  1595. Xlong
  1596. X    spool_size,        /* size of spool mail regardless of current folder */
  1597. X    last_size,        /* the last size of the mailfile since last check */
  1598. X    time();        /* satisfy lint */
  1599. X
  1600. Xvoid
  1601. X    error(), getmail(), mail_status(), sign_letter(),
  1602. X    init(), display_msg(), cleanup(), fs_error();
  1603. X    /* printf(), fclose(), fflush(), fputs(), fputc() */
  1604. X#ifdef TIOCGLTC
  1605. Xstruct ltchars ltchars;            /* tty character settings */
  1606. X#endif /* TIOCGLTC */
  1607. X#ifdef BSD /* (TIOCGETC) */
  1608. Xstruct tchars  tchars;            /* more tty character settings */
  1609. X#endif /* BSD (TIOCGETC) */
  1610. X
  1611. X#ifdef CURSES
  1612. X
  1613. X#define STANDOUT(y,x,s) standout(), mvaddstr(y,x,s), standend()
  1614. X#define redraw()    clearok(curscr, TRUE), wrefresh(curscr)
  1615. X
  1616. Xint
  1617. X    curses_init();    /* interpret commands via the curses interface */
  1618. X#endif /* CURSES */
  1619. X
  1620. Xint
  1621. X    mac_push(),        /* set up a string as a macro */
  1622. X    bind_it();        /* bind strings to functions or macros */
  1623. X
  1624. Xvoid
  1625. X    mac_flush();    /* Abandon macro processing (on error) */
  1626. X
  1627. X#ifdef SUNTOOL
  1628. Xvoid
  1629. X    timeout_cursors(), do_file_dir(), toggle_mail_items(), ok_box(),
  1630. X    read_mail(), opts_panel_item(), view_options(), toolquit(), wprint(),
  1631. X    update_list_textsw(), check_icons();
  1632. X
  1633. Xchar
  1634. X    *find_key(),    /* pass x,y coords to find which function key assoc. */
  1635. X    *panel_get(),          /* returns what has been typed in a panel item */
  1636. X    *tool_help,        /* help for tool-related things (sometimes, overlap) */
  1637. X    *more_prompt,    /* when NULL, we're paging a msg; else pager prompt */
  1638. X    blank[128];        /* use to clear to end of line */
  1639. X
  1640. Xint
  1641. X    time_out,        /* time out interval to wait for new mail */
  1642. X    is_iconic;        /* set if the mushview window is iconic. */
  1643. X
  1644. XNotify_value
  1645. X    do_check(),        /* check for new mail on timeout */
  1646. X    destroy_proc(),    /* Destroy procedure. */
  1647. X    scroll_textwin(),    /* Do fancy TEXTSW scrolling */
  1648. X    edit_msg_textwin();    /* Auto-positioning in compose TEXTSW */
  1649. X
  1650. XFrame tool;        /* Main frame. */
  1651. XFrame compose_frame;    /* Compose frame. */
  1652. XTextsw pager_textsw;    /* for "paging" messages and other lists.. */
  1653. XTextsw mfprint_sw;    /* Textsw in main mush frame for wprint() */
  1654. XTextsw cprint_sw;    /* Textsw in compose frame for wprint() */
  1655. XTextsw wprint_sw;    /* Current text subwindow for wprint() */
  1656. XCanvas hdr_sw;         /* Canvas for message headers */
  1657. XTty tty_sw;         /* subwindow which forks a shell (usually editor) */
  1658. X
  1659. XPixwin
  1660. X    *hdr_win;        /* pixwin for message headers */
  1661. X
  1662. Xstruct pixfont *mush_font;    /* array of fonts */
  1663. X
  1664. Xstruct itimerval mail_timer;    /* frequency to check for new mail */
  1665. X
  1666. Xextern Cursor l_cursor, m_cursor, r_cursor;
  1667. Xextern Icon mail_icon;
  1668. X
  1669. X/* When trapping events that represent scrolling actions */
  1670. Xtypedef enum {
  1671. X    MUSH_SCROLL_TO,
  1672. X    MUSH_SCROLL_RELATIVE,
  1673. X    MUSH_SCROLL_IGNORE,
  1674. X    MUSH_SCROLL_PASS_EVENT
  1675. X} Scroll_action;
  1676. X#endif /* SUNTOOL */
  1677. END_OF_FILE
  1678. if test 22786 -ne `wc -c <'mush/mush.h'`; then
  1679.     echo shar: \"'mush/mush.h'\" unpacked with wrong size!
  1680. fi
  1681. # end of 'mush/mush.h'
  1682. fi
  1683. if test -f 'mush/version.h' -a "${1}" != "-c" ; then 
  1684.   echo shar: Will not clobber existing file \"'mush/version.h'\"
  1685. else
  1686. echo shar: Extracting \"'mush/version.h'\" \(182 characters\)
  1687. sed "s/^X//" >'mush/version.h' <<'END_OF_FILE'
  1688. X/* @(#)version.h    (c) Copyright 1989 (Dan Heller) */
  1689. X
  1690. X#define MUSHNAME    "Mail User's Shell"
  1691. X#define RELEASE_DATE    "5/02/90"
  1692. X#define RELEASE        7
  1693. X#define REVISION    "1"
  1694. X#define PATCHLEVEL    1
  1695. END_OF_FILE
  1696. if test 182 -ne `wc -c <'mush/version.h'`; then
  1697.     echo shar: \"'mush/version.h'\" unpacked with wrong size!
  1698. fi
  1699. # end of 'mush/version.h'
  1700. fi
  1701. echo shar: End of archive 10 \(of 19\).
  1702. cp /dev/null ark10isdone
  1703. MISSING=""
  1704. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1705.     if test ! -f ark${I}isdone ; then
  1706.     MISSING="${MISSING} ${I}"
  1707.     fi
  1708. done
  1709. if test "${MISSING}" = "" ; then
  1710.     echo You have unpacked all 19 archives.
  1711.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1712. else
  1713.     echo You still need to unpack the following archives:
  1714.     echo "        " ${MISSING}
  1715. fi
  1716. ##  End of shell archive.
  1717. exit 0
  1718.  
  1719.