rs@uunet.UU.NET (Rich Salz) (09/18/87)
Submitted-by: island!argv@Sun.COM (Dan Heller) Posting-number: Volume 11, Issue 52 Archive-name: mush5.7/Part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 12)." # Contents: aliases.c curs_io.c dates.c execute.c folders.c # main_panel.c rite.c sort.c PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'aliases.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'aliases.c'\" else echo shar: Extracting \"'aliases.c'\" \(4554 characters\) sed "s/^X//" >'aliases.c' <<'END_OF_FILE' X/* (c) copyright @(#)aliases.c 2.4 10/15/86 (Dan Heller) */ X X#include "mush.h" X X/* X * do_alias handles aliases, header settings, functions, and fkeys. X * since they're all handled in the same manner, the same routine is X * used. argv[0] determines which to use. X * alias is given here as an example X * X * alias identify all aliases X * alias name identify alias X * alias name arg1 arg2 arg3... -> name="arg1 arg2 arg3"; call set_option X * unalias arg1 [arg2 arg3 ... ] unalias args X * X * same is true for dealing with your own headers. X * (also the expand command) X * always return -1 since it nas no effect on messages X */ Xdo_alias(argc, argv) Xregister char **argv; X{ X register char *cmd = *argv, *p; X struct options **list; X char firstchar = *cmd, buf[BUFSIZ]; X X if (argc == 0) X return -1; X if (firstchar == 'u') X firstchar = cmd[2]; X if (*++argv && !strcmp(*argv, "-?")) { /* doesn't apply for fkeys */ X register char *help_str; X if (firstchar == 'a' || firstchar == 'e') X help_str = "alias"; X else if (firstchar == 'c') X help_str = "func_help"; X else if (firstchar == 'f') X help_str = "fkey_help"; X else X help_str = "own_hdrs"; X return help(0, help_str, cmd_help); X } X X if (firstchar == 'a') X list = &aliases; X else if (firstchar == 'c') X list = &functions; X else if (firstchar == 'f') X list = &fkeys; X else X list = &own_hdrs; X X if (*cmd == 'u') { X if (!*argv) X print("%s what?\n", cmd); X /* unset a list separated by spaces or ',' */ X else while (*argv) { X if (!strcmp(*argv, "*")) /* unset everything */ X while (*list) X (void) un_set(list, (*list)->option); X else if (!un_set(list, *argv)) X print("\"%s\" isn't set\n", *argv); X argv++; X } X return -1; X } X X if (!*argv && *cmd != 'e') { X /* just type out all the aliases or own_hdrs */ X (void) do_set(*list, NULL); X return -1; X } X X if (*cmd == 'e') { /* command was "expand" (aliases only) */ X if (!*argv) X print("expand which alias?\n"); X else X do { X print("%s: ", *argv); X if (p = alias_to_address(*argv)) X print("%s\n", p); X } while (*++argv); X return -1; X } X X /* at this point, *argv now points to a variable name ... X * check for hdr -- if so, *argv better end with a ':' (check *p) X */ X if (list == &own_hdrs && !(p = index(*argv, ':'))) { X print("header labels must end with a ':' (%s)\n", *argv); X return -1; X } X if (!argv[1] && !index(*argv, '=')) X if (p = do_set(*list, *argv)) X print("%s\n", p); X else X print("%s is not set\n", *argv); X else { X (void) argv_to_string(buf, argv); X if ((p = any(buf, " \t=")) && *p != '=') X *p = '='; X argv[0] = buf; X argv[1] = NULL; X (void) add_option(list, argv); X } X return -1; X} X X/* takes string 's' which can be a name or list of names separated by X * spaces or commas and checks to see if each is aliased to something else. X * return address of the static buf. X */ Xchar * Xalias_to_address(s) Xregister char *s; X{ X static char buf[BUFSIZ]; X register char *p = s, *p2, *tmp; X char newbuf[BUFSIZ]; X static int recursive; X X if (!aliases) X return s; X if (!s || !*s) { X print("No recipeints!?!\n"); X return NULL; X } X skipspaces(0); X if (!recursive) { X bzero(buf, BUFSIZ); X p2 = buf; /* if we're starting all this, p2 starts at &buf[0] */ X } else X p2 = buf+strlen(buf); /* else, pick up where we left off */ X X if (++recursive == 30) { X print("alias references too many addresses!\n"); X recursive = 0; X return NULL; X } X /* find a comma, space, or newline -- if none exists, still go thru once */ X for (s = p; (p = any(s, ", \n")) || *s; s = p) { X if (p) X *p++ = 0; /* null terminate, comma/space/newline was found */ X else X for(p = s; *p; p++); /* last in list; go to end of string */ X X /* if this is an alias, recurse this routine to expand it out */ X if ((tmp = do_set(aliases, s)) && *tmp) { X if (!alias_to_address(strcpy(newbuf, tmp))) X return NULL; X else X p2 = buf+strlen(buf); X /* Now, make sure the buffer doesn't overflow */ X } else if (strlen(s) + (p2-buf) + 2 > BUFSIZ) { /* add " " + NULL */ X print("address length too long.\n"); X recursive = 0; X return NULL; X } else { X /* append the new alias (or unchanged address) onto the buffer */ X p2 += Strcpy(p2, s); X p2 += Strcpy(p2, ", "); /* two Strcpy's is faster than sprintf */ X } X skipspaces(0); X } X if (recursive) X recursive--; X if (!recursive) X *(p2-2) = 0; /* get rid of last ", " if end of recursion */ X return buf; X} END_OF_FILE if test 4554 -ne `wc -c <'aliases.c'`; then echo shar: \"'aliases.c'\" unpacked with wrong size! fi # end of 'aliases.c' fi if test -f 'curs_io.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'curs_io.c'\" else echo shar: Extracting \"'curs_io.c'\" \(5704 characters\) sed "s/^X//" >'curs_io.c' <<'END_OF_FILE' X/* @(#)curs_io.c (c) copyright 3/18/87 (Dan Heller) */ X X/* curs_io.c -- curses based I/O */ X#include "mush.h" X X#ifdef CURSES X#include "bindings.h" X#endif CURSES X X#ifdef Addch X#undef Addch X#endif Addch X X#ifndef CURSES X X#define Addch(c) if (isoff(glob_flags, ECHO_FLAG)) \ X fputc(c, stdout), fflush(stdout) X X#else X X/* see end of Getstr */ X#define Addch(c) \ X if (iscurses) \ X addch(c), refresh(); \ X else if (isoff(glob_flags, ECHO_FLAG)) \ X fputc(c, stdout), fflush(stdout) X#endif CURSES X X/* X * get a string of at most 'length' chars. X * allow backspace-space-backspace, kill word and kill line X * (options set by user in stty). X * length is the max length this string can get. offset is from beginning X * of string. X * input of ^D returns -1; otherwise, return the number of chars in string. X */ X#define backspace() { Addch('\b'); Addch(' '); Addch('\b'); } X XGetstr(String, length, offset) Xchar String[]; Xregister int length; X{ X register int c; X register int count = offset; X X while ((c = getchar()) != '\n' && c != 4 /* ^D */ && c != EOF && X isoff(glob_flags, WAS_INTR)) { X /* echo isn't set, so whatever the character, enter it */ X if (ison(glob_flags, ECHO_FLAG) && count < length) X String[count++] = c; X else if (c == _tty.sg_erase || c == 8 || c == 127) { X if (count) { X backspace() /* macro */ X count--; X } else if (!count && iscurses) { X String[0] = '\0'; X return -1; X } X } else if (c == _tty.sg_kill) { X if (count) { X do X backspace() /* macro */ X while (--count); X } X } else X#ifndef TIOCGLTC X if (c == '\022') /* system doesn't have ltchars */ X#else X if (c == ltchars.t_rprntc) /* reprint line */ X#endif TIOCGLTC X String[count] = 0, printf("\n%s", String); X else X#ifndef TIOCGLTC X if (c == '\027') /* system doesn't have ltchars */ X#else X if (c == ltchars.t_werasc) /* word erase */ X#endif TIOCGLTC X while (count) { X backspace(); X String[count--] = 0; X if (!count || (String[count-1]== ' '&& !isspace(String[count]))) X break; X } X else if (c == '\t') X do { X Addch(' '); X String[count] = ' '; X } while (++count % 8 && count < length); X else if (count == length) X bell(); X else if (c > 31 && c != 127) { X Addch(c); X String[count++] = c; X } X } X if (c == 4 || c == EOF || ison(glob_flags, WAS_INTR)) { /* ^D */ X if (feof(stdin)) X clearerr(stdin); X return -1; X } X if (count && String[count-1] == '\\') { X int count2; X if (isoff(glob_flags, ECHO_FLAG)) X putchar('\n'); X if ((count2 = Getstr(&String[count-1], length - count + 1, 0)) == -1) X return -1; X return count + count2; X } X if (!iscurses && isoff(glob_flags, ECHO_FLAG)) X putchar('\n'); X while (count > 0 && isspace(String[count-1])) X --count; X String[count] = 0; X return count; X} X X#undef backspace X#undef Addch X X#ifdef CURSES X/* curses based "more" like option */ Xvoid Xc_more() X{ X register char c; X X print_more("--more--"); X while ((c = getchar()) != ' ' && c != '\n') X bell(); X if (!iscurses && c != '\n') X while (getchar() != '\n'); X} X X/* X * prompt for a carriage return, but return whatever user types unless X * it's a character which he might regret (like 'q' or 'x'). Ignore X * interrupts (kind of) because we have nowhere to longjmp to. When we X * return, we'll setjmp again (top of loop.c) X */ Xhit_return() X{ X int c; X X turnon(glob_flags, IGN_SIGS); X iscurses = FALSE; X (void) check_new_mail(); X iscurses = TRUE; X mail_status(1), addstr("...continue... "), refresh(); X c = getcmd(); X turnoff(glob_flags, IGN_SIGS); X X /* don't let the user type something he might regret */ X if (c == C_QUIT || c == C_EXIT) X return 0; X return c; X} X Xcurses_msg_list(str, list, m_list) Xregister char *str, *list; Xchar m_list[]; X{ X register char *p = NULL; X X print(str); X if (Getstr(list, COLS-13, 0) <= 0 || !(p = do_range(list, m_list)) || X (p == list && *p && *p != '$' && *p != '^')) { X if (p) X print("Invalid message list: %s", p); X return 0; X } X move(LINES-1, 0), refresh(); X return 1; X} X Xcurs_vars(which, cntd_cmd) Xint which; /* really, a char */ Xint *cntd_cmd; X{ X char c, buf[128], buf2[128], *string; X struct options **list; X X switch(which) { X case C_OWN_HDR : string = "own_hdrs", list = &own_hdrs; X when C_ALIAS : string = "alias", list = &aliases; X when C_IGNORE : string = "ignore", list = &ignore_hdr; X when C_VAR_SET : string = "set", list = &set_options; X otherwise : clr_bot_line(); return; X } X X print("%s [? Set Unset All]: ", string); X c = getchar(); X clr_bot_line(); X switch (Lower(c)) { X /* if help, print help -- if "all", show all settings. */ X case '?' : case 'a' : X if (c == '?') { X if (!strcmp(string, "set")) { X print("which variable? [All <var>]: "); X if ((c = Getstr(buf, COLS-40, 0)) < 0) X return; X clr_bot_line(); X if (c > 0) { X Lower(*buf); X if (!strcmp(buf, "a")) X (void) strcpy(buf, "all"); X if (!strcmp(buf, "all")) X *cntd_cmd = 1; X (void) cmd_line(sprintf(buf2, "set ?%s", buf),msg_list); X return; X } X } X /* help returns next command (hit_return) */ X help(0, string, cmd_help); X *cntd_cmd = 1; X return; X } X *cntd_cmd = 1; X do_set(*list, NULL); X X /* if set, prompt for string and let user type */ X when 's' : X print("set: "); X c = Getstr(buf, COLS-18, 0); X clr_bot_line(); X if (c > 0) X (void) cmd_line(sprintf(buf2, "%s %s", string, buf), msg_list); X X /* if unset, just as easy as set! */ X when 'u' : X print("unset: ", string); X if (Getstr(buf, COLS-18, 0) > 0 && !un_set(list, buf)) { X print("%s isn't set", buf); X if (*cntd_cmd) X putchar('\n'); X } X } X} X X#endif CURSES END_OF_FILE if test 5704 -ne `wc -c <'curs_io.c'`; then echo shar: \"'curs_io.c'\" unpacked with wrong size! fi # end of 'curs_io.c' fi if test -f 'dates.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dates.c'\" else echo shar: Extracting \"'dates.c'\" \(6037 characters\) sed "s/^X//" >'dates.c' <<'END_OF_FILE' X/* @(#)dates.c 1.1 (c) copyright 10/15/86 (Dan Heller) */ X X#include "mush.h" X Xchar *day_names[] = { X "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" X}; Xchar *month_names[] = { /* imported in pick.c */ X "Jan", "Feb", "Mar", "Apr", "May", "Jun", X "July", "Aug", "Sep", "Oct", "Nov", "Dec" X}; X X/* Time() returns a string according to criteria: X * if "now" is 0, then the current time is gotten and used. X * else, use the time described by now X * opts points to a string of args which is parsed until an unknown X * arg is found and opts will point to that upon return. X * valid args are T (time of day), D (day of week), M (month), Y (year), X * N (number of day in month -- couldn't think of a better letter). X */ Xchar * XTime(opts, now) Xregister char *opts; Xlong now; X{ X static char time_buf[30]; X struct tm *T; X register char *p = time_buf; X long x; X X if (!opts) X return NULL; X if (now) X x = now; X else X (void) time(&x); X T = localtime(&x); X for (;; opts++) { X switch(*opts) { X case 'T': (void) sprintf(p, "%d:%02d", (T->tm_hour) ? X ((T->tm_hour <= 12) ? T->tm_hour : T->tm_hour - 12) : 12, X T->tm_min); X when 'D': (void) strcpy(p, day_names[T->tm_wday]); X when 'M': (void) strcpy(p, month_names[T->tm_mon]); X when 'Y': (void) sprintf(p, "%d", T->tm_year); X when 'N': (void) sprintf(p, "%d", T->tm_mday); X otherwise: *--p = 0; return time_buf; X } X p += strlen(p); X *p++ = ' '; X } X} X X/* find the date of a message and return a string of the same form X * described by parse_date() below. X */ Xchar * Xmsg_date(n) Xregister int n; X{ X register char *p, *p2 = NULL; X char line[256]; X X /* not in use */ X /* try the easy way out first -- This is potentially a serious kludge X * because not all message-id lines are right. -- most of the time, X * this is correct. it's not correct from messages from strange X * mailers (non-sendmail) they do a different format in message-id. X if ((p = header_field(n, "message-id")) && (p2 = index(p, '<'))) { X p = p2+1; X if (p2 = index(p, '.')) { X *p2 = 0; X return p; X } X } X */ X X /* else, get the "date" line, if that fails, get the date in "From" line */ X if ((p = header_field(n, "date")) && (p2 = parse_date(p))) X return p2; X X (void) fseek(tmpf, msg[n].m_offset, L_SET); X (void) fgets(line, BUFSIZ, tmpf); X if (!(p = index(line, ' ')) || !(p2 = index(p+1, ' '))) X return NULL; X p = p2; X X if (!(p2 = parse_date(p))) X print("Message %d has bad date: %s\n", n+1, p); X return p2; X} X X/* parse date and return a string that looks like X * "%2d%2d%2d%2d%2d", yr,mo,date,hrs,mins X */ Xchar * Xparse_date(p) Xregister char *p; X{ X static char buf[11]; X int Month = 0, Day = 0, Year = 0, Hours = -1, Mins = -1; X X skipspaces(0); X X /* Possible combinations that we could have: X * day_number month_name year_number time timezone ... X * day_name month_name day_number time year_number X * day_name month_name day_number year_number time X * day_name day_number month_name year_number time X * day_number month_name year_number time X * day_number month_name year_number time-timezone (day) X * ^no colon separator X * day_name month_name day_number time timezone year_number X * day_number-month_name-year time X * day_name, day_number-month_name-year time X */ X if (sscanf(p, "%d %s %2d %d:%d", &Day,buf,&Year,&Hours,&Mins) == 5 X || X sscanf(p, "%*s %s %d %d:%d:%*d %d", buf,&Day,&Hours,&Mins,&Year) == 5 X || X sscanf(p, "%*s %s %d %d %d:%d", buf,&Day,&Year,&Hours,&Mins) == 5 X || X sscanf(p, "%*s %d %s %d %d:%d", &Day,buf,&Year,&Hours,&Mins) == 5 X || X sscanf(p, "%d %s %d %d:%d", &Day,buf,&Year,&Hours,&Mins) == 5 X || X sscanf(p, "%d %s %d %2d%2d", &Day,buf,&Year,&Hours,&Mins) == 5 X || X sscanf(p, "%*s %s %d %d:%d:%*d %*s %d", X buf, &Day, &Hours, &Mins, &Year) == 5 X || X sscanf(p,"%d-%[^-]-%d %d:%d", &Day, buf, &Year, &Hours, &Mins) == 5 X || X sscanf(p,"%*s %d-%[^-]-%d %d:%d", &Day, buf, &Year, &Hours, &Mins) == 5) { X if (Year > 1900) X Year -= 1900; X if ((Month = month_to_n(buf)) == -1) { X print("bad month: %s\n", p); X return NULL; X } X return sprintf(buf, "%02d%02d%02d%02d%02d", Year,Month,Day,Hours,Mins); X } X print("Unknown date format: %s\n", p); X return NULL; X} X X/* pass a string in the form described above, put into string. "yr" is X * not used, but is here anyway in case you want to modify it to use it. X */ Xchar * Xdate_to_string(Date) Xchar *Date; X{ X static char buf[30]; X int yr, mon, day, hr, mins; X char a_or_p, *p = buf; X X (void) sscanf(Date, "%2d%2d%2d%2d%02d", &yr, &mon, &day, &hr, &mins); X a_or_p = (hr < 12)? 'a': 'p'; X p += strlen(sprintf(p, "%s %2.d, ", month_names[mon-1], day)); X (void) sprintf(p, "%2.d:%02d%cm", X (hr)? (hr <= 12)? hr: hr - 12: 12, mins, a_or_p); X return buf; X} X X#define JAN 1 X#define FEB 2 X#define MAR 3 X#define APR 4 X#define MAY 5 X#define JUN 6 X#define JUL 7 X#define AUG 8 X#define SEP 9 X#define OCT 10 X#define NOV 11 X#define DEC 12 X X/* stolen direct from ELM */ Xmonth_to_n(name) Xregister char *name; X{ X /** return the month number given the month name... **/ X X register char ch; X X switch (lower(*name)) { X case 'a' : if ((ch = lower(name[1])) == 'p') X return(APR); X else if (ch == 'u') X return(AUG); X else return(-1); /* error! */ X case 'd' : return(DEC); X case 'f' : return(FEB); X case 'j' : if ((ch = lower(name[1])) == 'a') X return(JAN); X else if (ch == 'u') { X if ((ch = lower(name[2])) == 'n') X return(JUN); X else if (ch == 'l') X return(JUL); X else return(-1); /* error! */ X } X else return(-1); /* error */ X case 'm' : if ((ch = lower(name[2])) == 'r') X return(MAR); X else if (ch == 'y') X return(MAY); X else return(-1); /* error! */ X case 'n' : return(NOV); X case 'o' : return(OCT); X case 's' : return(SEP); X default : return(-1); X } X} END_OF_FILE if test 6037 -ne `wc -c <'dates.c'`; then echo shar: \"'dates.c'\" unpacked with wrong size! fi # end of 'dates.c' fi if test -f 'execute.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'execute.c'\" else echo shar: Extracting \"'execute.c'\" \(4414 characters\) sed "s/^X//" >'execute.c' <<'END_OF_FILE' X/* execute.c (c) copyright 10/28/86 (Dan Heller) */ X X#include "mush.h" X#ifdef BSD X#include <sys/wait.h> X#else X#ifndef SYSV X#include <wait.h> X#endif SYSV X#endif BSD X X#ifdef lint X#include <sys/resource.h> X#endif lint X Xexecute(argv) Xchar **argv; X{ X#ifdef SYSV X int status; X#else X union wait status; X#endif SYSV X#ifdef SIGCONT X int (*oldstop)(), (*oldcont)(); X#endif SIGCONT X int pid, (*oldint)(), (*oldquit)(); X X#ifdef SUNTOOL X if (istool) { X print("Editing letter..."); X X panel_set(abort_item, PANEL_SHOW_ITEM, FALSE, 0); X panel_set(send_item, PANEL_SHOW_ITEM, FALSE, 0); X panel_set(edit_item, PANEL_SHOW_ITEM, FALSE, 0); X win_setrect(tty_sw->ts_windowfd, &msg_rect); X msg_rect.r_height = 0; X win_setrect(msg_sw->ts_windowfd, &msg_rect); X if ((exec_pid = ttysw_fork(tty_sw->ts_data, argv, X &tty_sw->ts_io.tio_inputmask, X &tty_sw->ts_io.tio_outputmask, X &tty_sw->ts_io.tio_exceptmask)) == -1) X error("%s failed", *argv), sigchldcatcher(); X Debug("tty pid = %d\n", exec_pid); X return; X } X#endif SUNTOOL X oldint = signal(SIGINT, SIG_IGN); X oldquit = signal(SIGQUIT, SIG_IGN); X#ifdef SIGCONT X oldstop = signal(SIGTSTP, SIG_DFL); X oldcont = signal(SIGCONT, SIG_DFL); X#endif SIGCONT X turnon(glob_flags, IGN_SIGS); X X echo_on(); X if ((exec_pid = vfork()) == 0) { X (void) signal(SIGINT, SIG_DFL); X (void) signal(SIGQUIT, SIG_DFL); X execvp(*argv, argv); X if (errno == ENOENT) X print("%s: command not found.\n", *argv); X else X error(*argv); X _exit(-1); X } X /* parent's got to do something; sigchldcatcher will do waiting X * if other forks die (sendmail), then this wait will catch them, X * This loop will really get -1, cuz sigchldcatcher will catch all else. X */ X while ((pid = wait(&status) != -1) && pid != exec_pid) X Debug("The exec loop caught a signal? (pid = %d)\n", pid); X /* reset our ttymodes */ X echo_off(); X (void) signal(SIGINT, oldint); X (void) signal(SIGQUIT, oldquit); X#ifdef SIGCONT X (void) signal(SIGTSTP, oldstop); X (void) signal(SIGCONT, oldcont); X#endif SIGCONT X turnoff(glob_flags, IGN_SIGS); X} X Xsigchldcatcher() X{ X#ifdef SUNTOOL X struct rect rect; X#endif SUNTOOL X#ifdef SYSV X int status; X#else X union wait status; X#endif SYSV X int pid; X X#ifdef BSD X /* The follwoing SHOULDN'T be necessary, but it is!!! ttysw_fork() X * returns the pid of the thing that it executes, but that's not the X * pid that dies! There are many procs that might die from ttysw_fork X * one of them is the process, another is the tty, etc... other X * procs that might die are sendmail, fortune, etc... tool_sigchld() X * handles these, but we can't let it have control unless we KNOW the X * editor is done. X * so if what we catch is not the exec_pid from ttysw_fork(), then X * send ourselves a sigchld to go thru this routine again. mush -d X */ X while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) { X Debug("%d died...\n", pid); X if (pid == exec_pid) X break; X } X#else X#ifndef SYSV X while ((pid = wait2(&status, WNOHANG)) > 0 && pid != exec_pid) X Debug("%d died...\n", pid); X#else SYSV X while ((pid = wait((int *)0)) > 0 && pid != exec_pid) X Debug("%d died...\n", pid); X#endif SYSV X#endif BSD X#ifndef SUNTOOL X } X#else SUNTOOL X if (pid != exec_pid || exec_pid <= 0) /* if the editor didn't die, return */ X return; X /* editor died -- reset exec_pid so no one thinks we're running */ X exec_pid = 0; X /* only the tool needs to continue from here. Reset the win */ X if (istool < 1) X return; X tool_sigchld(tool); X print("Editor done"); X win_getrect(tty_sw->ts_windowfd, &msg_rect); X if (!msg_rect.r_height) { X print_more(" (well, something just happened)"); X return; X } X rect.r_top = rect.r_left = rect.r_height = 0; X rect.r_width = msg_rect.r_width; X win_setrect(tty_sw->ts_windowfd, &rect); X win_setrect(msg_sw->ts_windowfd, &msg_rect); X panel_set(comp_item, PANEL_SHOW_ITEM, FALSE, 0); X panel_set(send_item, PANEL_SHOW_ITEM, TRUE, 0); X panel_set(edit_item, PANEL_SHOW_ITEM, TRUE, 0); X panel_set(abort_item, PANEL_SHOW_ITEM, TRUE, 0); X wprint("(continue editing letter.)\n"); X pw_char(msg_win, txt.x,txt.y, PIX_SRC, fonts[curfont], '_'); X} X Xsigtermcatcher() X{ X ttysw_done(tty_sw->ts_data); X if (ison(glob_flags, IS_GETTING)) X rm_edfile(-1); X cleanup(SIGTERM); X} X#endif SUNTOOL END_OF_FILE if test 4414 -ne `wc -c <'execute.c'`; then echo shar: \"'execute.c'\" unpacked with wrong size! fi # end of 'execute.c' fi if test -f 'folders.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'folders.c'\" else echo shar: Extracting \"'folders.c'\" \(4933 characters\) sed "s/^X//" >'folders.c' <<'END_OF_FILE' X/* @(#)folders.c (c) copyright 10/18/86 (Dan Heller) */ X X#include "mush.h" X X/* folder %[user] --new mailfile is the spool/mail/login file [user]. X * folder # --new mailfile is the folder previous to the current folder X * folder & --new mailfile is ~/mbox (or whatever "mbox" is set to) X * folder +file --new mailfile is in the directory "folder"; name is 'file' X * folder "path" --full path name or the one in current working directory. X * X * in all cases, changes are updated unless a '!' is specified after the X * folder command (e.g. "f!", "folder !" "fo!" .. all permutations) X * as usual, if new mail has arrived before the file is copied back, then X * user will be notified beforehand. X * X * RETURN -1 on error -- else return 0. All bits in msg_list are set to true. X */ Xfolder(argc, argv, list) Xregister char **argv, list[]; X{ X int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0; X static char oldfolder[256]; X char *tmp, *newfolder = NULL, buf[256]; X X if (ison(glob_flags, DO_PIPE)) { X print("You can't pipe to the folder command"); X return -1; X } X while (*++argv && (**argv == '-' || **argv == '!')) X if (!strcmp(*argv, "-?")) X return help(0, "folder_help", cmd_help); X else if (!strcmp(*argv, "-N")) X no_hdrs = 1; X else if (!strcmp(*argv, "-r")) X do_read_only = 1; X else if (!strcmp(*argv, "!")) X turnoff(glob_flags, DO_UPDATE); X X if (updating) X (void) strcpy(buf, mailfile); X else { X if (!*argv) { X print("%s\n", mailfile); X return 0; X } X if (!strcmp(*argv, "#")) X if (!*oldfolder) { X print("No previous folder\n"); X return -1; X } else X newfolder = oldfolder; X else if (!strcmp(*argv, "&")) { X if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder) X newfolder = DEF_MBOX; X } else X newfolder = *argv; X n = 0; X tmp = getpath(newfolder, &n); X if (n == -1) { X print("%s: %s\n", newfolder, tmp); X return -1; X } else if (n == 1) { X print("%s: is a directory\n", tmp); X return -1; X } X /* strcpy so copyback() below (which calls getpath) doesn't change X * the data that tmp intended to point to. X */ X (void) strcpy(buf, tmp); X } X if (access(buf, R_OK)) { X error("Can't open %s", buf); X return -1; X } X if (access(buf, W_OK)) X do_read_only = 1; X#ifdef SUNTOOL X if (istool) lock_cursors(); X#endif SUNTOOL X if (ison(glob_flags, DO_UPDATE) && !copyback()) { X#ifdef SUNTOOL X if (istool) unlock_cursors(); X#endif SUNTOOL X /* could be an error, but new mail probably came in */ X return -1; X } X (void) strcpy(oldfolder, mailfile); X strdup(mailfile, buf); X do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY); X last_size = spool_size = 0L; X msg_cnt = 0; X turnoff(glob_flags, CONT_PRNT); X X turnon(glob_flags, IGN_SIGS); X /* clear the tempfile */ X fclose(tmpf); X if (!(tmpf = fopen(tempfile, "w"))) { X error("error truncating %s", tempfile); X turnoff(glob_flags, IGN_SIGS); X return -1; X } X getmail(); X last_msg_cnt = msg_cnt; /* for check_new_mail */ X (void) mail_size(); X#ifdef SUNTOOL X if (istool) { X panel_set(next_scr, PANEL_SHOW_ITEM, FALSE, 0); X panel_set(prev_scr, PANEL_SHOW_ITEM, FALSE, 0); X pw_rop(hdr_win, 0,0, hdr_rect.r_width, hdr_rect.r_height,PIX_CLR,0,0,0); X } X#endif SUNTOOL X current_msg = 0; X turnoff(glob_flags, IGN_SIGS); X X /* now sort messages according a user_defined default */ X if (!updating && msg_cnt > 1 && is_spool(mailfile) && X (tmp = do_set(set_options, "sort"))) { X (void) sprintf(buf, "sort %s", tmp); X if (argv = make_command(buf, TRPL_NULL, &argc)) { X /* msg_list can't be null for do_command and since we're not X * interested in the result, call sort directly X */ X (void) sort(argc, argv, NULL); X free_vec(argv); X } X } X turnoff(glob_flags, DO_UPDATE); X X while (current_msg < msg_cnt && isoff(msg[current_msg].m_flags, UNREAD)) X current_msg++; X if (current_msg == msg_cnt) X current_msg = 0; X X if (!istool && !iscurses) X mail_status(0); X /* be quite if we're piping */ X if ((istool || !updating) && isoff(glob_flags, IS_PIPE) && X (istool || !no_hdrs) && msg_cnt) X (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list); X#ifdef SUNTOOL X if (istool) { X if (!msg_cnt) X print("No Mail in %s\n", mailfile); X else if (isoff(glob_flags, IS_GETTING) && !getting_opts) X display_msg(current_msg, (long)0); X unlock_cursors(); X } X#endif SUNTOOL X if (list) { X clear_msg_list(list); X bitput(list, list, msg_cnt, =~) /* macro */ X } X return 0; X} X Xfolders(argc, argv) Xregister char **argv; X{ X register char *p; X char buf[128], unused[MAXMSGS_BITS]; X X if (!(p = do_set(set_options, "folder")) || !*p) { X print("You have no folder variable set.\n"); X return -1; X } X (void) sprintf(buf, "ls %s", p); X if (argv = make_command(buf, TRPL_NULL, &argc)) X (void) do_command(argc, argv, unused); X return -1; X} END_OF_FILE if test 4933 -ne `wc -c <'folders.c'`; then echo shar: \"'folders.c'\" unpacked with wrong size! fi # end of 'folders.c' fi if test -f 'main_panel.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'main_panel.c'\" else echo shar: Extracting \"'main_panel.c'\" \(9355 characters\) sed "s/^X//" >'main_panel.c' <<'END_OF_FILE' X/* "@(#)main_panel.c (c) copyright 10/18/86 (Dan Heller) */ X X#include "mush.h" X Xmake_main_panel(choice_args, button_args) Xchar **choice_args, **button_args; X{ X /* main panel stuff: */ X panel_sw = panel_create(tool, X PANEL_HEIGHT, 80, X 0); X main_panel = (Panel)panel_sw->ts_data; X X quit_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 4, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Done", 6, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Done", X PANEL_CHOICE_STRINGS, "Close to Icon", X "Quit Tool", X "Help", X 0, X PANEL_NOTIFY_PROC, toolquit, X 0); X X help_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 79, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Help", 4, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Available Help", X PANEL_CHOICE_STRINGS, "General", X "Help with \"help\"", X "The Mouse", X "Windows", X "Function Keys", X "Message headers", X "Message lists", X 0, X PANEL_NOTIFY_PROC, do_help, X 0); X X read_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 136, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Next", 4, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Next Message", X PANEL_CHOICE_STRINGS, "Read Next", "Help", 0, X PANEL_NOTIFY_PROC, read_mail, X 0); X X respond_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 193, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Reply", 5, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Respond to Current Message", X PANEL_CHOICE_STRINGS, "Sender Only", X "Sender Only (include msg)", X "All Recipients", X "All Recipients (include msg)", X "Help", 0, X PANEL_NOTIFY_PROC, respond_mail, X 0); X X delete_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 259, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Delete", 6, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Delete/Undelete Messages", X PANEL_CHOICE_STRINGS, "Delete current message", X "Delete All Messages", X "Undelete current message", X "Undelete All Messages", X "Delete message \"range\"", X "Undelete message \"Range\"", X "Help", 0, X PANEL_NOTIFY_PROC, delete_mail, X 0); X X sort_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 334, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Sort", 4, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Sort Messages", X PANEL_CHOICE_STRINGS, "By Date", X "By Author", X "By Subject", X "By Subject (ignore Re:)", X "By Status", X "Help", 0, X PANEL_NOTIFY_PROC, do_sort, X 0); X X option_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 391, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Opts", 4, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Mail Options", X PANEL_CHOICE_STRINGS, "Set Options", "Function keys", X "Help", 0, X PANEL_NOTIFY_PROC, p_set_opts, X 0); X X alias_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 448, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Aliases", 7, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Mail Aliases", X PANEL_CHOICE_STRINGS, "Current Aliases", X "Add/Change alias", X "Unalias", "Help", 0, X PANEL_NOTIFY_PROC, p_set_opts, X 0); X X comp_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 532, X PANEL_ITEM_Y, 4, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Compose", 8, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Compose a letter", X PANEL_CHOICE_STRINGS, "Help", 0, X PANEL_NOTIFY_PROC, do_compose, X 0); X X file_item = panel_create_item(main_panel, PANEL_TEXT, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 4, X PANEL_ITEM_Y, 30, X PANEL_LABEL_FONT, fonts[DEFAULT], X PANEL_SHOW_MENU, TRUE, X PANEL_LABEL_STRING, "filename:", X PANEL_MENU_CHOICE_STRINGS, "Save message without message header",0, X PANEL_VALUE_DISPLAY_LENGTH, 35, X PANEL_NOTIFY_STRING, "\n\r", X PANEL_NOTIFY_PROC, file_dir, X 0); X X input_item = panel_create_item(main_panel, PANEL_TEXT, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 373, X PANEL_ITEM_Y, 30, X PANEL_SHOW_ITEM, FALSE, X PANEL_SHOW_MENU, TRUE, X PANEL_LABEL_FONT, fonts[DEFAULT], X PANEL_VALUE_DISPLAY_LENGTH, 20, X PANEL_NOTIFY_STRING, "\n\r", X PANEL_NOTIFY_PROC, text_done, X 0); X X print_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 4, X PANEL_ITEM_Y, 50, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Printer", 7, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Printing Messages", X PANEL_CHOICE_STRINGS, "Help", 0, X PANEL_NOTIFY_PROC, do_lpr, X 0); X X folder_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 88, X PANEL_ITEM_Y, 50, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "folder", 6, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Change folder", X PANEL_CHOICE_STRINGS, "System Mailbox", X "Main Mailbox", X "Last Accessed Folder", X 0, X PANEL_NOTIFY_PROC, do_file_dir, X 0); X X add_folder_to_menu(folder_item, 3); X X save_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 163, X PANEL_ITEM_Y, 50, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Save", 4, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Save messages", X PANEL_CHOICE_STRINGS, "Save in ~/mbox", X "Save message \"range\"", X 0, X PANEL_NOTIFY_PROC, do_file_dir, X 0); X X add_folder_to_menu(save_item, 2); X X cd_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 220, X PANEL_ITEM_Y, 50, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "chdir", 5, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Change Working Directory", X PANEL_CHOICE_STRINGS, "Print Current directory", X "HOME directory", X "Private Mail directory.", X "Help", 0, X PANEL_NOTIFY_PROC, do_file_dir, X 0); X X update_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 286, X PANEL_ITEM_Y, 50, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Update", 6, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Updating folders", X PANEL_CHOICE_STRINGS, "Help", 0, X PANEL_NOTIFY_PROC, do_update, X 0); X X send_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 361, X PANEL_ITEM_Y, 50, X PANEL_SHOW_ITEM, FALSE, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Send", 6, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Send Letter", X PANEL_CHOICE_STRINGS, "Help", 0, X PANEL_NOTIFY_PROC, do_send, X 0); X X edit_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 436, X PANEL_ITEM_Y, 50, X PANEL_SHOW_ITEM, FALSE, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Editor", 4, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Editing", X PANEL_CHOICE_STRINGS, "Help", 0, X PANEL_NOTIFY_PROC, do_edit, X 0); X X abort_item = panel_create_item(main_panel, PANEL_BUTTON, X PANEL_ATTRIBUTE_LIST, button_args, X PANEL_ITEM_X, 511, X PANEL_ITEM_Y, 50, X PANEL_SHOW_ITEM, FALSE, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Abort", 5, fonts[LARGE]), X PANEL_NOTIFY_PROC, abort_mail, X 0); X X font_item = panel_create_item(main_panel, PANEL_CHOICE, X PANEL_ATTRIBUTE_LIST, choice_args, X PANEL_ITEM_X, 577, X PANEL_ITEM_Y, 50, X PANEL_LABEL_IMAGE, X panel_button_image(main_panel, "Fonts", 5, fonts[LARGE]), X PANEL_MENU_TITLE_STRING, "Fonts", X PANEL_SHOW_MENU_MARK, TRUE, X PANEL_CHOICE_FONTS, fonts[0], fonts[1], fonts[2], 0, X PANEL_CHOICE_STRINGS, "Default", "Small", "Large", 0, X PANEL_NOTIFY_PROC, change_font, X 0); X} X X/* X * Open the user's mail folder (either user set or default path) and find all X * the files (assumed to be mail folders) and add them to the menu list of X * folders to use. X */ Xadd_folder_to_menu(item, n) Xstruct panel_item *item; Xregister int n; X{ X register FILE *pp = NULL_FILE; X register char *p = do_set(set_options, "folder"); X register char *tmp = NULL; X int x = 0; X char buf[128], path[128]; X X if (p) { X tmp = getpath(p, &x); X if (x == -1) { X if (errno != ENOENT) X print("%s: %s\n", p, tmp); X tmp = NULL; X } X } X if (p = tmp) { X p = sprintf(buf, "%s %s", LS_COMMAND, p); X if (!(pp = popen(buf, "r"))) X error(buf); X else { X *path = '+'; X while (fgets(path+1, 128, pp)) { X struct stat s_buf; X if (p = index(path+1, '\n')) X *p = 0; X (void) sprintf(buf, "%s/%s", tmp, path+1); X if (stat(buf, &s_buf) || s_buf.st_mode & S_IFDIR) X continue; X panel_set(item, PANEL_CHOICE_STRING, n++, path, 0); X } X } X } X panel_set(item, PANEL_CHOICE_STRING, n, "Help", 0); X} END_OF_FILE if test 9355 -ne `wc -c <'main_panel.c'`; then echo shar: \"'main_panel.c'\" unpacked with wrong size! fi # end of 'main_panel.c' fi if test -f 'rite.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rite.c'\" else echo shar: Extracting \"'rite.c'\" \(4613 characters\) sed "s/^X//" >'rite.c' <<'END_OF_FILE' X/* rite.c (c) copyright 1986 (Dan Heller) */ X X#include "mush.h" X X#define LASTLINE (msg_rect.r_height - l_height(LARGE)-5) X Xstatic char *_unctrl[] = { X "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K", X "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", X "^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_", X " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", X ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", X "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", X "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", X "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", X "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", X "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "^?" X}; X Xstatic char String[BUFSIZ]; Xstatic int count, backchars, save_orig_x; X Xchar * Xrite(c) Xregister char c; X{ X static int literal_next; X X if (c == ltchars.t_lnextc || literal_next) { X if (literal_next) X Addch(c); X else /* don't call Addch to prevent cursor from advancing */ X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], '^'); X literal_next = !literal_next; X return NULL; X } X literal_next = 0; X if (c == _tty.sg_erase) { X if (count) X backspace(), String[count--] = 0; X } else if (c == _tty.sg_kill) { X if (count) { X Clrtoeol(msg_win, txt.x = save_orig_x, txt.y,curfont); X String[count=0] = 0; X } X } else if (c == ltchars.t_werasc) X while (count) { X backspace(); X String[count--] = 0; X if (!count || (String[count-1]==' ' && !isspace(String[count]))) X break; X } X else if (c == '\n' || c == '\r' || c == 13) { X String[count] = 0; X if ((txt.y += l_height(curfont)) >= LASTLINE && !getting_opts) X scroll_win(1); X /* else Clrtoeol(msg_win, txt.x, txt.y, curfont); */ X count = 0, txt.x = 5; X return String; X } else if (c == 12) { X if (ison(glob_flags, IS_GETTING)) X Addch(c); X else do_clear(); X } else if (count == BUFSIZ-1) X print("Text too long for String!"), count--; X else if (c == '\t') X do Addch(' '); X while (count % 8 && count < BUFSIZ); X else X Addch(c); X return NULL; X} X Xbackspace() X{ X if (backchars) { X pw_text(msg_win, save_orig_x, txt.y, PIX_SRC, fonts[curfont], X &String[--backchars]); X Clrtoeol(msg_win, msg_rect.r_width-10-l_width(curfont), txt.y, curfont); X } else if ((txt.x -= l_width(curfont)) >= 5) X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' '); X else X txt.x = 5; X} X Xstatic XAddch(c) Xregister char c; X{ X if (!count) X save_orig_x = txt.x, bzero(String, BUFSIZ); X if (c > 31 && c != 127) X String[count++] = c; X else { X Addch('^'); X Addch(_unctrl[c][1]); X return; X } X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], c); X if ((txt.x += l_width(curfont)) <= msg_rect.r_width-5-l_width(curfont)) X return; X if (getting_opts) { X pw_text(msg_win, save_orig_x, txt.y, PIX_SRC, fonts[curfont], X &String[++backchars]); X txt.x -= l_width(curfont); X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' '); X } else { X txt.x = 5; X if ((txt.y += l_height(curfont)) >= LASTLINE) X scroll_win(1); X } X} X XAddstr(s) Xregister char *s; X{ X char buf[BUFSIZ]; X register int cnt = 0, max_len; X register char *p = buf, newline = 0; X X max_len = (msg_rect.r_width - 10) / l_width(curfont) + 1; X X while ((*p = *s++) && *p != '\n' && cnt < max_len) X if (*p == '\t') X do *p++ = ' '; X while (++cnt % 8); X else p++, cnt++; X *p = 0; X X if (*--s) X newline = *s, *s = 0; /* newline may or may not be a '\n' */ X else X s = 0; X X if (*buf) { X if (msg_pix) { X struct pr_prpos pixr; X pixr.pr = msg_pix; X pixr.pos = txt; X pf_text(pixr, PIX_SRC, fonts[curfont], buf); X } else X pw_text(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], buf); X txt.x += cnt * l_width(curfont); X } X if (newline) { X if (newline != '\n') X *s = newline; X if ((txt.y += l_height(curfont)) >= LASTLINE && !msg_pix) X scroll_win(1); X txt.x = 5; X if (newline == '\n' && !*++s) X return; X Addstr(s); X } X} X Xtool_more(p) Xregister char *p; X{ X int percent; X /* we are typing -- scrool the window */ X if (!msg_pix) { X scroll_win(1); X return; X } X if (p) X print(p); X else { X if ((percent = (still_more * 100) / msg_pix->pr_size.y) >= 100) X print( "--End of Message %d--", current_msg+1); X else X print("--Message %d--(%d%%)", current_msg+1, percent); X if (ison(glob_flags, IS_GETTING)) X print_more(" ('q' returns to type-in mode)"); X } X} END_OF_FILE if test 4613 -ne `wc -c <'rite.c'`; then echo shar: \"'rite.c'\" unpacked with wrong size! fi # end of 'rite.c' fi if test -f 'sort.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sort.c'\" else echo shar: Extracting \"'sort.c'\" \(5125 characters\) sed "s/^X//" >'sort.c' <<'END_OF_FILE' X/* signals.c 1.1 (c) copyright 1986 (Dan Heller) */ X X#include "mush.h" X/* #define MYQSORT */ X Xstatic int order; Xstatic jmp_buf sortbuf; X Xsort(argc, argv, list) Xregister int argc; Xregister char *argv[], list[]; X{ X int status_cmp(), author_cmp(), date_cmp(), subject_cmp(), subj_with_re(); X int (*oldint)(), (*oldquit)(); X int (*how)() = status_cmp; X int n, offset = -1, range = 0; X X order = 1; X X while (argc && *++argv) { X n = 0; X while (argv[0][n]) X switch(argv[0][n++]) { X case '-': order = -1; X when 'd': how = date_cmp; X when 'a': how = author_cmp; X when 's': how = subject_cmp; X when 'R': how = subj_with_re; X when 'S': how = status_cmp; X otherwise: return help(0, "sort_help", cmd_help); X } X } X if (msg_cnt <= 1) { X print("Not enough messages to sort.\n"); X return -1; X } X on_intr(); X X if (list && ison(glob_flags, IS_PIPE)) { X for (n = 0; n < msg_cnt; n++) X if (msg_bit(list, n)) { X if (offset < 0) X offset = n; X range++; X } else if (offset >= 0) X break; X } else X offset = 0, range = msg_cnt; X X if (range < 2) X print("Range not broad enough to sort anything\n"); X else { X Debug("Sorting %d messages starting at message %d\n", range, offset+1); X X if (setjmp(sortbuf) == 0) X qsort((char *)&msg[offset], range, sizeof (struct msg), how); X else X print("WARNING: Sorting interrupted: unpredictable order.\n"); X turnon(glob_flags, DO_UPDATE); X } X off_intr(); X return -1; X} X X#ifdef MYQSORT Xqsort(base, len, siz, compar) Xregister struct msg *base; Xint (*compar)(); X{ X register int i, swapping; X struct msg temp; X X do { X swapping = 0; X for (i = 0; i < len-1; ++i) { X if (compar(base+i, base+i+1) > 0) { X temp = base[i]; X base[i] = base[i+1]; X base[i+1] = temp; X swapping = 1; X } X } X } while (swapping); X} X#endif MYSORT X Xstatus_cmp(msg1, msg2) Xregister struct msg *msg1, *msg2; X{ X if (ison(glob_flags, WAS_INTR)) X longjmp(sortbuf, 1); X if (msg1 < msg || msg2 < msg) { X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg); X return 0; X } X if (msg1->m_flags == msg2->m_flags) X return 0; X if (ison(msg1->m_flags, DELETE) && isoff(msg2->m_flags, DELETE)) X return order; X if (isoff(msg1->m_flags, DELETE) && ison(msg2->m_flags, DELETE)) X return -order; X if (isoff(msg1->m_flags, OLD) && ison(msg2->m_flags, OLD)) X return -order; X if (ison(msg1->m_flags, OLD) && isoff(msg2->m_flags, OLD)) X return order; X if (ison(msg1->m_flags, UNREAD) && isoff(msg2->m_flags, UNREAD)) X return -order; X if (isoff(msg1->m_flags, UNREAD) && ison(msg2->m_flags, UNREAD)) X return order; X if (ison(msg1->m_flags,PRESERVE) && isoff(msg2->m_flags,PRESERVE)) X return -order; X if (isoff(msg1->m_flags,PRESERVE) && ison(msg2->m_flags,PRESERVE)) X return order; X X return order; X} X Xauthor_cmp(msg1, msg2) Xregister struct msg *msg1, *msg2; X{ X char buf1[BUFSIZ], buf2[BUFSIZ]; X X if (ison(glob_flags, WAS_INTR)) X longjmp(sortbuf, 1); X if (msg1 < msg || msg2 < msg) { X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg); X return 0; X } X (void) reply_to(msg1 - msg, 0, buf1); /* "0" for "author only" */ X (void) reply_to(msg2 - msg, 0, buf2); X Debug("author: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2); X return strcmp(buf1, buf2) * order; X} X X/* X * compare subject strings from two messages. X * If Re is appended, so be it -- if user wants to ignore Re: use 'R' flag. X */ Xsubj_with_re(msg1, msg2) Xregister struct msg *msg1, *msg2; X{ X char buf1[256], buf2[256]; X X if (ison(glob_flags, WAS_INTR)) X longjmp(sortbuf, 1); X if (msg1 < msg || msg2 < msg) { X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg); X return 0; X } X (void) subject_to(msg1 - msg, buf1); X (void) subject_to(msg2 - msg, buf2); X Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg,buf1,msg2-msg,buf2); X return strcmp(buf1, buf2) * order; X} X X/* X * Subject comparison ignoring Re: subject_to() appends an Re: if there is X * any subject whatsoever. If so, skip 4 chars. If not, set to "" X */ Xsubject_cmp(msg1, msg2) Xregister struct msg *msg1, *msg2; X{ X char buf1[256], buf2[256], *p1, *p2; X X if (ison(glob_flags, WAS_INTR)) X longjmp(sortbuf, 1); X if (msg1 < msg || msg2 < msg) { X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg); X return 0; X } X if (p1 = subject_to(msg1 - msg, buf1)) X p1 += 4; X else X p1 = ""; X if (p2 = subject_to(msg2 - msg, buf2)) X p2 += 4; X else X p2 = ""; X Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg, p1, msg2-msg, p2); X return strcmp(p1, p2) * order; X} X Xdate_cmp(msg1, msg2) Xregister struct msg *msg1, *msg2; X{ X char buf1[11], buf2[11]; X X if (ison(glob_flags, WAS_INTR)) X longjmp(sortbuf, 1); X if (msg1 < msg || msg2 < msg) { X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg); X return 0; X } X (void) strcpy(buf1, msg_date(msg1-msg)); X (void) strcpy(buf2, msg_date(msg2-msg)); X Debug("dates: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2); X return strcmp(buf1, buf2) * order; X} END_OF_FILE if test 5125 -ne `wc -c <'sort.c'`; then echo shar: \"'sort.c'\" unpacked with wrong size! fi # end of 'sort.c' fi echo shar: End of archive 2 \(of 12\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 12 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0