home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
pc
/
source
/
mush.lzh
/
mush.17
< prev
next >
Wrap
Text File
|
1990-05-06
|
56KB
|
1,872 lines
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
# "End of archive 17 (of 19)."
# Contents: mush/README-7.1 mush/hdr_sw.c mush/malloc.c
# mush/misc_frame.c mush/strings.c
# Wrapped by argv@turnpike on Wed May 2 13:59:49 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mush/README-7.1' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mush/README-7.1'\"
else
echo shar: Extracting \"'mush/README-7.1'\" \(11036 characters\)
sed "s/^X//" >'mush/README-7.1' <<'END_OF_FILE'
XThis is release 7.1.0 of the SunView implementation of mush.
X
XVersion 7.1.0 differs from 7.0.4 mostly in the appearance of the screen
Xand the additional functionality that is allowed to show through to the
Xtool from the underlying interpreter. This is a significant enough change
Xin "look and feel" that the revision number was increased from 0 to 1.
X
XThanks to Bill Randle <billr@saab.cna.tek.com> for extensive SunOS 3.5
Xtesting, and to Bill and also Don Lewis <del@mlb.semi.harris.com> for
Xtheir contributions to the new toolmode composition features and function
Xkey handling.
X
XTool mode changes include:
X * Compilation now keys on definitions of SUN_4_1, SUN_4_0 or SUN_3_5
X in makefile.sun, rather than assuming SunOS4.0 when SIGRET=void.
X You still have to define SUNTOOL to get the tool mode capability.
X If you define SUNTOOL but not the others, SUN_4_0 is assumed.
X * The header summary display window has a scrollbar; the <Prev> and
X <Next> buttons for scrolling are gone.
X * The placement of buttons and items has changed a lot. Buttons and
X items dealing with folders and general setup have moved to the top
X of the frame, and items dealing with individual messages and with
X composition have been placed in a single row between the headers
X and messsage display subwindows.
X * The <Folders> and <Save> buttons each have a text entry item.
X Furthermore, file completion with the ESC key works in those items.
X * The <Sort> menu has been unscrambled, so you actually get the sort
X criteria that you select. (Don't ask.)
X * The <Aliases> and <Headers> buttons have moved into a menu under
X the <Options> button. This clears up some confusion about exactly
X what it was that <Headers> meant, and provides a hook for future
X addition of a window for defining your own outgoing message headers.
X * The <Display> button is gone; its operations are now handled by
X opening the <Options> frame and toggling show_deleted or no_reverse.
X * The small one-line print window is gone; messages previously shown
X there now go to the scrollable status window. There may be some
X remaining bugs with missing newlines here. This frees up some more
X file descriptors in SunOS 3.5, to keep other things working longer.
X * Function keys are recognized in most parts of the main frame. In
X anticipation of the day when window manager function keys can be
X redefined, the messages about "L7 not defined" etc. are still shown
X unless suppressed through $quiet (see below).
X * The composition frame has more control buttons, providing more of
X the functions of line and curses mode message composition. Some
X of the "chattiness" of message composition has gone away. In fact,
X the whole chatty subwindow in the compose frame has gone away,
X possibly to return in a later patch when a better way to decide
X what frame a message should go to has been worked out. In the
X meantime, all messages go to the main frame.
X * Tilde escapes are supported in the tool mode composition textsw,
X with a few minor exceptions accessible from the control buttons.
X * Typing a <return> while entering header field text in tool mode
X will move automatically to the next header when this is sensible.
X The cursor becomes a bent arrow to indicate that this will happen.
X * User-definable icons can be installed through the $mail_icon and
X $newmail_icon variables, and $quiet has a field to suppress the
X message-number label so your pretty pictures won't be trashed.
X * Files that are not readable as folders are left out of the menus
X for the <Folder> and <Save> items.
X
XGeneral changes include:
X
X * There is a new defined constant, DIRECTORY, which indicates whether
X your system has BSD-compatible directory-access routines. It turns
X out to be much too hard to figure this out on an OS-by-OS basis.
X DIRECTORY is automatically defined when BSD is defined, and is in
X the default CFLAGS in makefile.hpux; you others are on your own.
X * Some compilers were confused by "/*" appearing in the META string
X defined in glob.h. The characters in META have been rearranged.
X * Using "exit" in a nested "if" in a source/init file no longer
X causes error messages about "missing endif".
X * Redefining "folder" via a "cmd" in .mushrc no longer causes the
X initial folder load to bomb. Similarly with "sort".
X * Date parsing and sorting now understand timezones. There may
X still be some rough edges in date parsing on some of the less
X common date formats, but RFC-822 and ctime (From_ line) dates
X are handled correctly. If the dates mush displays are really
X off the wall, the order of the sscanf's in parse_date() may need
X to be changed, or we may need to add some cases rather than
X using partial matches to skip missing timezone fields. There
X are also some strange nonstandard abbreviations out there (what,
X for example, is ECT?) which will all be treated as GMT unless
X you hack them into the tables in dates.c. Missing timezones are
X treated as the local zone to get the date-received right (the
X From_ line ctime-date almost never has a timezone).
X * Mush now warns you if a file you attempt to load does not "look
X like" a folder (i.e. no messages can be read). If you are already
X in the shell, this leaves you in an empty folder as it did before.
X If you are just starting up (e.g. with "mush -f"), mush will exit.
X * Additional checking is now done when collecting new mail and when
X updating folders to detect corruptions, warn the user, and allow
X a chance to recover. Mush still reinitializes the spool folder if
X it shrinks, but if this is detected at update time (as opposed to
X new-mail-check time), the user is allowed to abort the update and
X salvage the current folder contents.
X * Curses mode now respects the user's presetting of $crt, unless the
X user's value is larger than the actual screen size. This allows
X "set crt=2" to be used to force use of $pager.
X
XChanges in commands:
X
Xmush -h -
X The -h (-draft) option will now accept "-" as a filename indicating
X standard input. Note that this causes the input message to be sent
X immediately; interactive use cannot be combined with redirected input.
X The internal "mail -h" command will NOT interpret "-" as standard in.
X
Xalts *user
X This syntax, analogous to the $autosign2 syntax, allows you to specify
X any user name anywhere as "you" for purposes of $metoo, etc.
X
Xfolder -n
X This command changes folders without updating; it replaces the old
X "folder !" notation, though the old form is still supported. See
X also the general notes above for behavior on attempts to load files
X that are not folders.
X
Xfrom pattern
X Given an argument that is not parseable as a message list, "from" will
X automatically invoke "pick -f pattern". Mixing message lists and
X patterns is slightly counter-intuitive; if the message list precedes
X the pattern, it will restrict the pattern search to that list, e.g.
X "from 3-7 johnsmith" will show those messages in the range 3-7 that
X are from johnsmith. If the message list follows the pattern, it will
X not be detected at all, but will be considered part of the pattern.
X Also, "from jim bob sally" will treat the entire "jim bob sally" list
X as a single pattern, as "pick" would; this may change in the future.
X
Xpipe -p /pat1/,/pat2/
X The pattern supplied may now have the form /pat1/,/pat2/ to indicate
X that extraction should begin at pat1 and end at pat2, inclusive.
X Patterns are still matched literally at beginning-of-line (no regex
X matching), and there is not currently any way to imbed a slash in
X patterns of this form. To allow searching for file paths, slashes
X are significant only if the second slash is followed by a comma.
X
Xsave/copy
X Unless told to clobber the file (-f), these commands now check that
X the file to which they are appending "looks like" a folder. If the
X file seems to be something else, the user is prompted to confirm the
X save or copy.
X
Xset
X Several minor fixes. Piping to "set" now clears the variable if the
X input message list is empty, rather than leaving the old value. For
X backwards compatibility, however, an unset variable does not become
X set when an empty message list is piped to it. Also, some of the
X more esoteric abuses of the variable=value syntax have either been
X made legal (`set var=' is the same as `set var') or made illegal
X (`set var=value = value' won't create a variable named "var=value").
X
Xsort
X Sorting by multiple criteria at once is now supported. The flags to
X sort have changed; "-" to reverse sorting is now obsolete, replaced
X by "-r", and all the sort criteria should now be prefixed with a "-"
X (-a,-d,-l,-R,-s,-S) like options to any other command. A significant
X subset of the old syntax is still recognized as a special case.
X
XNew/changed variables:
X
X $cmd_help
X (Also $tool_help) The path given for this variable may contain
X the usual filename metacharacters (~+).
X
X $hangup
X When set, mush updates the folder on SIGHUP instead of saving
X the tempfile. This is a bit dangerous -- in rare circumstances
X (mainly when two or more MUAs are modifying the same folder)
X some new mail could be lost. Old mail should never be lost.
X
X $hdr_format
X The format spec %Z returns the time zone part of the date.
X
X $mail_icon
X Names an icon file to be used in the normal case, when no new
X mail is present. This icon will replace the mailbox with the
X flag down.
X
X $newmail_icon
X Names an icon file to be used when new mail is present, replacing
X the mailbox with the flag up.
X
X $output
X The message-list output of the last successful command is stored
X in this variable. This allows easy recovery from broken pipes
X etc. Note that any successful command that does not produce a
X message list will clear $output (e.g. "echo").
X
X $quiet
X If the field "newmail" is present in the multi-value, the usual
X "New mail (#X): ..." messages are not displayed. The new mail
X is still automatically incorporated into the mailbox. In tool
X mode, this shuts off the new mail bell (the "tool" field still
X silences ALL tool mode bells).
X
X If the field "fkey" is present in tool mode, warning messages
X about unbound keys are not printed.
X
X If the field "iconlabel" is present in tool mode, the current
X number of messages is not displayed in the mush icon.
X
X $status
X This is set to the success (0) or failure (-1) status of the
X previously executed command. Note that some curses-mode commands
X return a failure status to indicate that the display has been
X corrupted even if the command itself succeeded, so this variable
X is mostly useful in scripts.
END_OF_FILE
if test 11036 -ne `wc -c <'mush/README-7.1'`; then
echo shar: \"'mush/README-7.1'\" unpacked with wrong size!
fi
# end of 'mush/README-7.1'
fi
if test -f 'mush/hdr_sw.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mush/hdr_sw.c'\"
else
echo shar: Extracting \"'mush/hdr_sw.c'\" \(11559 characters\)
sed "s/^X//" >'mush/hdr_sw.c' <<'END_OF_FILE'
X/* @(#)hdr_sw.c (c) copyright 2/17/90 (Dan Heller) */
X
X/* This file handles all the header subwindow code. It would be much
X * better if this subwindow, which displays the headers for the current
X * folder, were a textsw. That way, this file would go away completely.
X * Until then, we have to create the window (canvas), define an event
X * handler for when events happen in this window, create our own scrollbar,
X * figure out when the user scrolls with it, attach our own popup menu to
X * the canvas, handle events for that, let's see... kitchen sink? Oh,
X * that's over there in the corner.
X */
X#include "mush.h"
X#ifdef SUN_4_0 /* SunOS 4.0+ */
X#include <sunwindow/win_keymap.h>
X#endif /* SUN_4_0 */
X
Xextern Panel hdr_panel;
Xextern void hdr_io(), fkey_interposer();
X
Xstatic Notify_value scroll_hdr();
Xstatic void msg_menu_func(), do_menu(), msg_menu_notify();
Xstatic Menu msg_menu;
Xstatic Menu_item cur_msg_item;
X
Xvoid
Xmake_hdr_sw(parent)
XFrame parent;
X{
X Textsw tmpsw;
X
X if (!(hdr_sw = window_create(parent, CANVAS,
X WIN_HEIGHT, 10 + screen*l_height(),
X WIN_WIDTH, WIN_EXTEND_TO_EDGE,
X WIN_BELOW, hdr_panel,
X WIN_EVENT_PROC, hdr_io,
X CANVAS_AUTO_CLEAR, TRUE,
X CANVAS_RETAINED, TRUE,
X WIN_CONSUME_KBD_EVENTS,
X WIN_ASCII_EVENTS, WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, NULL,
X WIN_IGNORE_KBD_EVENTS,
X WIN_UP_ASCII_EVENTS, NULL,
X WIN_CONSUME_PICK_EVENTS,
X LOC_WINENTER, WIN_MOUSE_BUTTONS, LOC_MOVE, NULL,
X WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
X NULL)))
X perror("hdr_sw"), cleanup(0);
X hdr_win = canvas_pixwin(hdr_sw);
X (void) notify_interpose_event_func(hdr_sw, fkey_interposer, NOTIFY_SAFE);
X (void) notify_interpose_event_func(hdr_sw, scroll_hdr, NOTIFY_SAFE);
X scrollbar_set((Scrollbar)window_get(hdr_sw, WIN_VERTICAL_SCROLLBAR),
X SCROLL_NORMALIZE, FALSE,
X SCROLL_ADVANCED_MODE, TRUE,
X SCROLL_LINE_HEIGHT, l_height(),
X SCROLL_VIEW_LENGTH, screen,
X NULL);
X#ifdef SUN_4_0 /* SunOS 4.0+ */
X /* This is a particularly ugly hack. If Sun only documented the correct
X * way to set up the key mapping for a window the way that textsw's do
X * then we wouldn't have to do anything this awful. Maybe in 4.2.....
X *
X * The object here is to get the same translation table for our header
X * canvas as for a textsw (more or less anyway). This way the arrow
X * keys and such work right.
X */
X tmpsw = window_create(parent, TEXTSW, NULL);
X#ifdef SUN_4_1
X keymap_from_fd[(int)window_get(hdr_sw, WIN_FD)].keymap =
X keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].keymap;
X keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].keymap = (Keymap *) 0;
X#else /* !SUN_4_1 */
X keymap_from_fd[(int)window_get(hdr_sw, WIN_FD)].kf_keymap =
X keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].kf_keymap;
X keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].kf_keymap = (Keymap *) 0;
X#endif /* SUN_4_1 */
X (void) window_destroy(tmpsw);
X#endif /* SUN_4_0 */
X}
X
Xstatic Notify_value
Xscroll_hdr(canvas, event, arg, type)
XCanvas canvas;
XEvent *event;
XNotify_arg arg;
XNotify_event_type type;
X{
X int amount, count, i;
X int show_deleted = !!do_set(set_options, "show_deleted");
X char *argv[3], msgnum[8];
X Scrollbar sb;
X argv[0] = "headers";
X argv[1] = msgnum;
X argv[2] = NULL;
X
X switch (decode_scroll((Notify_client) canvas, event, screen, &amount)) {
X case MUSH_SCROLL_PASS_EVENT:
X switch(ID) {
X case SCROLL_ENTER:
X case SCROLL_EXIT:
X return NOTIFY_IGNORED;
X case SCROLL_REQUEST:
X sb = (Scrollbar)arg;
X switch( (Scroll_motion)
X scrollbar_get(sb, SCROLL_REQUEST_MOTION)) {
X case SCROLL_LINE_FORWARD:
X amount = 1;
X break;
X case SCROLL_LINE_BACKWARD:
X amount = -1;
X break;
X case SCROLL_ABSOLUTE:
X i = (int)scrollbar_get(sb, SCROLL_VIEW_START);
X if (!show_deleted) {
X count = i;
X for (i = 0; i < msg_cnt-1; i++)
X if (!ison(msg[i].m_flags, DELETE) &&
X count-- == 0)
X break;
X }
X (void) sprintf(msgnum, "%d", i+1);
X argv[1] = msgnum;
X (void) do_hdrs(2, argv, NULL);
X return(NOTIFY_DONE);
X default:
X amount =
X (int)scrollbar_get(sb, SCROLL_VIEW_START) -
X (int)scrollbar_get(sb, SCROLL_LAST_VIEW_START);
X break;
X }
X break;
X default:
X return notify_next_event_func(canvas, event, arg, type);
X }
X break;
X case MUSH_SCROLL_IGNORE:
X return NOTIFY_IGNORED;
X case MUSH_SCROLL_TO:
X if (amount == 1) {
X argv[1] = "1";
X (void) do_hdrs(2, argv, NULL);
X return NOTIFY_DONE;
X } else {
X (void) sprintf(msgnum, "%d", msg_cnt - screen + 1);
X argv[1] = msgnum;
X (void) do_hdrs(2, argv, NULL);
X return NOTIFY_DONE;
X }
X }
X if (amount == screen)
X argv[1] = "+";
X else if (amount == -screen)
X argv[1] = "-";
X else if (amount >= 0) {
X if (amount < screen)
X (void) sprintf(msgnum, "%d", min(n_array[amount]+1, msg_cnt-1));
X else {
X /* so much for layering */
X for (i = n_array[0]+1; i < msg_cnt-1 && amount > 0; i++)
X if (show_deleted || !ison(msg[i].m_flags, DELETE))
X amount--;
X (void) sprintf(msgnum, "%d", i);
X }
X } else {
X /* so much for layering */
X for (i = n_array[0]; i > 0 && amount < 0; i--)
X if (show_deleted || !ison(msg[i-1].m_flags, DELETE))
X amount++;
X (void) sprintf(msgnum, "%d", i + 1);
X }
X (void) do_hdrs(2, argv, NULL);
X return NOTIFY_DONE;
X}
X
X/*
X * Routines to handle io on the hdr_sw (canvas).
X */
X
X/* if MENU button goes down on a hdr, drawbox around hdr and popup menu */
X#define draw(x1,y1,x2,y2) (void) pw_vector(hdr_win, x1,y1,x2,y2,PIX_XOR,1)
X#define box(x1,y1,x2,y2) \
X draw(x1,y1, x1,y2), draw(x1,y2, x2,y2), \
X draw(x2,y2, x2,y1), draw(x2,y1, x1,y1)
X
X#define READ_MSG (char *)'r'
X#define DEL_MSG (char *)'d'
X#define UNDEL_MSG (char *)'u'
X#define REPL_MSG (char *)'R'
X#define SAVE_MSG (char *)'s'
X#define PRNT_MSG (char *)'p'
X#define PRE_MSG (char *)'P'
X#define HELP_MSG (char *)'H'
X
X/*ARGSUSED*/
Xvoid
Xhdr_io(canvas, event, arg)
XCanvas canvas;
XEvent *event;
Xcaddr_t arg;
X{
X static int which_cursor;
X int line;
X
X if (ID == WIN_REPAINT) {
X if (is_iconic != (int) window_get(tool, FRAME_CLOSED)) {
X check_new_mail();
X
X /* Reload time with value of timeout upon timer expiration. */
X mail_timer.it_interval.tv_sec = time_out;
X
X mail_timer.it_value.tv_sec = time_out;
X (void) notify_set_itimer_func(tool, do_check,
X ITIMER_REAL, &mail_timer, (struct itimerval *) 0);
X is_iconic = 0;
X }
X }
X
X /* make cursor change which button is lit */
X switch (which_cursor) {
X case 0 : (void) window_set(canvas, WIN_CURSOR, l_cursor, NULL);
X when 1 : (void) window_set(canvas, WIN_CURSOR, m_cursor, NULL);
X when 2 : (void) window_set(canvas, WIN_CURSOR, r_cursor, NULL);
X }
X
X which_cursor = (which_cursor+1) % 3;
X
X /* just return -- we just wanted to make the cursor flicker */
X if (ID == LOC_STILL || ID == LOC_MOVE || ID == LOC_WINENTER ||
X ID == LOC_RGNENTER || ID == KBD_USE || ID == KBD_DONE)
X return;
X
X if (event_is_button(event) && event_is_down(event)) {
X line = (event_y(event) - 5) / l_height();
X if (line < 0)
X line = 0;
X else if (line >= screen)
X line = screen - 1;
X if (!msg_cnt || n_array[line] > msg_cnt)
X return;
X if (ID == MS_RIGHT)
X do_menu(hdr_sw, event, window_get(hdr_sw, WIN_FD), n_array[line]);
X else if (ID == MS_MIDDLE) {
X set_isread(n_array[line]);
X msg_menu_func(DEL_MSG, n_array[line]);
X } else {
X int do_do_hdrs = 0;
X if (current_msg != n_array[line]) {
X current_msg = n_array[line];
X do_do_hdrs++;
X }
X if (ison(msg[current_msg].m_flags, UNREAD))
X do_do_hdrs++;
X (void) display_msg(n_array[line], (u_long)0);
X if (do_do_hdrs)
X (void) do_hdrs(0, DUBL_NULL, NULL);
X }
X } else
X window_default_event_proc(canvas, event, NULL);
X}
X
Xstatic struct menu_rec {
X char *str; /* Menu item label. */
X char *data; /* Menu item client data. */
X};
X
Xstatic void
Xget_msg_menu()
X{
X int i;
X Menu_item mi = NULL;
X
X static struct menu_rec msg_items[] = {
X { "Read", READ_MSG },
X { "Delete", DEL_MSG },
X { "Undelete", UNDEL_MSG },
X { "Reply", REPL_MSG },
X { "Save", SAVE_MSG },
X { "Preserve", PRE_MSG },
X { "Print", PRNT_MSG },
X { "Help", HELP_MSG },
X };
X
X msg_menu = menu_create(MENU_NOTIFY_PROC, msg_menu_notify, NULL);
X for (i = 0; i < ArraySize(msg_items); i++) {
X mi = menu_create_item(MENU_STRING, msg_items[i].str,
X MENU_CLIENT_DATA, msg_items[i].data,
X NULL);
X (void) menu_set(msg_menu, MENU_APPEND_ITEM, mi, NULL);
X }
X}
X
Xstatic void
Xmsg_menu_notify(menu, item)
XMenu menu;
XMenu_item item;
X{
X cur_msg_item = item;
X}
X
Xstatic void
Xdo_menu(can_sw, event, fd, message)
XCanvas can_sw;
XEvent *event;
Xint fd, message;
X{
X char *action;
X static char buf[16];
X
X if (!msg_cnt) {
X wprint("No Messages.\n");
X return;
X }
X if (fd) {
X int line;
X Rect *hdr_rect;
X
X if (!msg_menu)
X get_msg_menu();
X (void) sprintf(buf, "Message #%d", message+1);
X /* provide feedback about what message the menu references */
X for (line = 0; line <= n_array[screen-1]; line++)
X if (n_array[line] == message)
X break;
X hdr_rect = (Rect *)window_get(hdr_sw, WIN_RECT);
X box(0, 5 + line * l_height(),
X hdr_rect->r_width, 5 + (line+1) * l_height());
X /* show menu */
X menu_show(msg_menu, can_sw, event, NULL);
X /* remove feedback */
X box(0, 5 + line * l_height(),
X hdr_rect->r_width, 5 + (line+1) * l_height());
X /* if user selected something, figure out what was selected. */
X if (!cur_msg_item)
X return;
X action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA);
X cur_msg_item = (Menu_item)NULL;
X } else
X action = (char *) event;
X
X set_isread(message);
X switch ((int) action) {
X case SAVE_MSG : {
X extern Panel_item msg_num_item, save_item;
X (void) panel_set(msg_num_item, PANEL_VALUE,
X sprintf(buf, "%d", message+1), NULL);
X event_id(event) = MS_LEFT;
X do_file_dir(save_item, 0, event);
X (void) panel_set(msg_num_item, PANEL_VALUE, NO_STRING, NULL);
X }
X when HELP_MSG :
X help(0, "headers", tool_help);
X when PRNT_MSG : case PRE_MSG : case UNDEL_MSG : case DEL_MSG :
X msg_menu_func(action, message);
X when REPL_MSG : {
X extern Panel_item reply_item;
X (void) open_compose();
X /* reply_item shouldn't be here */
X respond_mail(reply_item, message, NO_EVENT);
X }
X otherwise :
X if (current_msg != message) {
X current_msg = message;
X (void) do_hdrs(0, DUBL_NULL, NULL);
X }
X#ifdef SUN_3_5
X /* Test for a shortage of file descriptors */
X if (nopenfiles(0) > 3)
X#endif /* SUN_3_5 */
X turnon(glob_flags, NEW_FRAME);
X more_prompt = compose_hdr(message);
X display_msg(message, (u_long)0);
X }
X}
X
X/* msg_menu_func() is a function called to perform message menu actions
X * that are either selected from the popup menu in the header window or
X * from mouse actions that function as accelerators.
X */
Xstatic void
Xmsg_menu_func(action, message)
Xchar *action;
X{
X int argc;
X register char **argv;
X char buf[32];
X
X wprint("Message #%d ", message+1);
X if (action == UNDEL_MSG || action == DEL_MSG)
X wprint("%sd.\n", sprintf(buf, "%selete",
X (action == DEL_MSG)? "d": "und"));
X else if (action == PRNT_MSG) {
X wprint("sent to printer.\n");
X (void) strcpy(buf, "lpr");
X } else if (action == PRE_MSG)
X wprint("%sd.\n", strcpy(buf, "preserve"));
X (void) sprintf(&buf[strlen(buf)], " %d", message+1);
X
X if (argv = make_command(buf, (char ***) DUBL_NULL, &argc))
X (void) do_command(argc, argv, msg_list);
X}
END_OF_FILE
if test 11559 -ne `wc -c <'mush/hdr_sw.c'`; then
echo shar: \"'mush/hdr_sw.c'\" unpacked with wrong size!
fi
# end of 'mush/hdr_sw.c'
fi
if test -f 'mush/malloc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mush/malloc.c'\"
else
echo shar: Extracting \"'mush/malloc.c'\" \(10827 characters\)
sed "s/^X//" >'mush/malloc.c' <<'END_OF_FILE'
X/*
X * This is a slightly modified version of the malloc.c distributed with
X * Larry Wall's perl 2.0 sources. RCS and sccs information has been
X * retained, but modified so that it will not actually affect checkin
X * or checkout of this file if revision control is used for Mush.
X *
X * Other changes include:
X * Removal of the ASSERT macro and other code related to the
X * preprocessor definition "debug"
X *
X * Replaced #include "perl.h" with #include "mush.h" (guess why)
X *
X * Warning messages are now printed with the mush Debug macro,
X * that is, they are normally suppressed
X *
X * Added a calloc() function, using mush's bzero()
X *
X * Also, the mush xfree() and free_vec() functions have been moved here.
X */
X
X#include "mush.h"
X
X/*
X * Compile this portion only if configured for INTERNAL_MALLOC
X */
X#ifdef INTERNAL_MALLOC
X#ifdef SYSV
X#include <memory.h>
X#define bcopy(src,dst,len) memcpy(dst,src,len)
X#endif /* SYSV */
X#define free xfree /* rename free for mush purposes */
X
X/* Begin modified perl malloc.c */
X
X/* Header: malloc.c,v 2.0 88/06/05 00:09:16 root Exp
X *
X * Log: malloc.c,v
X * Revision 2.0 88/06/05 00:09:16 root
X * Baseline version 2.0.
X *
X */
X
X#ifndef lint
Xstatic char sccsid[] = "malloc.c 4.3 (Berkeley) 9/16/83";
X#endif /* !lint */
X
X#define RCHECK
X/*
X * malloc.c (Caltech) 2/21/82
X * Chris Kingsley, kingsley@cit-20.
X *
X * This is a very fast storage allocator. It allocates blocks of a small
X * number of different sizes, and keeps free lists of each size. Blocks that
X * don't exactly fit are passed up to the next larger size. In this
X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
X * This is designed for use in a program that uses vast quantities of memory,
X * but bombs when it runs out.
X */
X
X/* I don't much care whether these are defined in sys/types.h--LAW */
X
X#undef u_char
X#define u_char unsigned char
X#undef u_int
X#define u_int unsigned int
X#undef u_short
X#define u_short unsigned short
X
X/*
X * The overhead on a block is at least 4 bytes. When free, this space
X * contains a pointer to the next free block, and the bottom two bits must
X * be zero. When in use, the first byte is set to MAGIC, and the second
X * byte is the size index. The remaining bytes are for alignment.
X * If range checking is enabled and the size of the block fits
X * in two bytes, then the top two bytes hold the size of the requested block
X * plus the range checking words, and the header word MINUS ONE.
X */
Xunion overhead {
X union overhead *ov_next; /* when free */
X struct {
X u_char ovu_magic; /* magic number */
X u_char ovu_index; /* bucket # */
X#ifdef RCHECK
X u_short ovu_size; /* actual block size */
X u_int ovu_rmagic; /* range magic number */
X#endif /* RCHECK */
X } ovu;
X#define ov_magic ovu.ovu_magic
X#define ov_index ovu.ovu_index
X#define ov_size ovu.ovu_size
X#define ov_rmagic ovu.ovu_rmagic
X};
X
X#define MAGIC 0xff /* magic # on accounting info */
X#define OLDMAGIC 0x7f /* same after a free() */
X#define RMAGIC 0x55555555 /* magic # on range info */
X#ifdef RCHECK
X#define RSLOP sizeof (u_int)
X#else /* !RCHECK */
X#define RSLOP 0
X#endif /* RCHECK */
X
X/*
X * nextf[i] is the pointer to the next free block of size 2^(i+3). The
X * smallest allocatable block is 8 bytes. The overhead information
X * precedes the data area returned to the user.
X */
X#define NBUCKETS 30
Xstatic union overhead *nextf[NBUCKETS];
Xextern char *sbrk();
X
X#ifdef MSTATS
X/*
X * nmalloc[i] is the difference between the number of mallocs and frees
X * for a given block size.
X */
Xstatic u_int nmalloc[NBUCKETS];
X#endif /* MSTATS */
X
Xchar *
Xmalloc(nbytes)
X register unsigned nbytes;
X{
X register union overhead *p;
X register int bucket = 0;
X register unsigned shiftr;
X
X /*
X * Convert amount of memory requested into
X * closest block size stored in hash buckets
X * which satisfies request. Account for
X * space used per block for accounting.
X */
X nbytes += sizeof (union overhead) + RSLOP;
X nbytes = (nbytes + 3) &~ 3;
X shiftr = (nbytes - 1) >> 2;
X /* apart from this loop, this is O(1) */
X while (shiftr >>= 1)
X bucket++;
X /*
X * If nothing in hash bucket right now,
X * request more memory from the system.
X */
X if (nextf[bucket] == (union overhead *)0)
X morecore(bucket);
X if ((p = (union overhead *)nextf[bucket]) == (union overhead *)0)
X return (NULL);
X /* remove from linked list */
X if (*((int*)p) > 0x10000000)
X Debug("Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p);
X nextf[bucket] = nextf[bucket]->ov_next;
X p->ov_magic = MAGIC;
X p->ov_index= bucket;
X#ifdef MSTATS
X nmalloc[bucket]++;
X#endif /* MSTATS */
X#ifdef RCHECK
X /*
X * Record allocated size of block and
X * bound space with magic numbers.
X */
X if (nbytes <= 0x10000)
X p->ov_size = nbytes - 1;
X p->ov_rmagic = RMAGIC;
X *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
X#endif /* RCHECK */
X return ((char *)(p + 1));
X}
X
X/*
X * Allocate more memory to the indicated bucket.
X */
Xstatic
Xmorecore(bucket)
X register bucket;
X{
X register union overhead *op;
X register int rnu; /* 2^rnu bytes will be requested */
X register int nblks; /* become nblks blocks of the desired size */
X register int siz;
X
X if (nextf[bucket])
X return;
X /*
X * Insure memory is allocated
X * on a page boundary. Should
X * make getpageize call?
X */
X op = (union overhead *)sbrk(0);
X if ((long)op & 0x3ff)
X sbrk(1024 - ((long)op & 0x3ff));
X /* take 2k unless the block is bigger than that */
X rnu = (bucket <= 8) ? 11 : bucket + 3;
X nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */
X if (rnu < bucket)
X rnu = bucket;
X op = (union overhead *)sbrk(1 << rnu);
X /* no more room! */
X if ((long)op == -1)
X return;
X /*
X * Round up to minimum allocation size boundary
X * and deduct from block count to reflect.
X */
X if ((long)op & 7) {
X op = (union overhead *)(((long)op + 8) &~ 7);
X nblks--;
X }
X /*
X * Add new memory allocated to that on
X * free list for this hash bucket.
X */
X nextf[bucket] = op;
X siz = 1 << (bucket + 3);
X while (--nblks > 0) {
X op->ov_next = (union overhead *)((caddr_t)op + siz);
X op = (union overhead *)((caddr_t)op + siz);
X }
X}
X
Xvoid
Xfree(cp)
X char *cp;
X{
X register int size;
X register union overhead *op;
X
X if (cp == NULL || debug < 5)
X return;
X op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
X if (op->ov_magic != MAGIC) {
X Debug("%s free() ignored\n",
X op->ov_magic == OLDMAGIC ? "Duplicate" : "Bad");
X return; /* sanity */
X }
X op->ov_magic = OLDMAGIC;
X#ifdef RCHECK
X if (op->ov_rmagic != RMAGIC) {
X Debug("Range check failed, free() ignored\n");
X return;
X }
X if (op->ov_index <= 13 &&
X *(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) != RMAGIC) {
X Debug("Range check failed, free() ignored\n");
X return;
X }
X#endif /* RCHECK */
X if (op->ov_index >= NBUCKETS)
X return;
X size = op->ov_index;
X op->ov_next = nextf[size];
X nextf[size] = op;
X#ifdef MSTATS
X nmalloc[size]--;
X#endif /* MSTATS */
X}
X
X/*
X * When a program attempts "storage compaction" as mentioned in the
X * old malloc man page, it realloc's an already freed block. Usually
X * this is the last block it freed; occasionally it might be farther
X * back. We have to search all the free lists for the block in order
X * to determine its bucket: 1st we make one pass thru the lists
X * checking only the first block in each; if that fails we search
X * ``reall_srchlen'' blocks in each list for a match (the variable
X * is extern so the caller can modify it). If that fails we just copy
X * however many bytes was given to realloc() and hope it's not huge.
X */
Xint reall_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
X
Xchar *
Xrealloc(cp, nbytes)
X char *cp;
X unsigned nbytes;
X{
X register u_int onb;
X union overhead *op;
X char *res;
X register int i;
X int was_alloced = 0;
X
X if (cp == NULL)
X return (malloc(nbytes));
X op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
X if (op->ov_magic == MAGIC) {
X was_alloced++;
X i = op->ov_index;
X } else {
X /*
X * Already free, doing "compaction".
X *
X * Search for the old block of memory on the
X * free list. First, check the most common
X * case (last element free'd), then (this failing)
X * the last ``reall_srchlen'' items free'd.
X * If all lookups fail, then assume the size of
X * the memory block being realloc'd is the
X * smallest possible.
X */
X if ((i = findbucket(op, 1)) < 0 &&
X (i = findbucket(op, reall_srchlen)) < 0)
X i = 0;
X }
X onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
X /* avoid the copy if same size block */
X if (was_alloced &&
X nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP)
X return(cp);
X if ((res = malloc(nbytes)) == NULL)
X return (NULL);
X if (cp != res) /* common optimization */
X bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
X if (was_alloced)
X free(cp);
X return (res);
X}
X
X/*
X * Search ``srchlen'' elements of each free list for a block whose
X * header starts at ``freep''. If srchlen is -1 search the whole list.
X * Return bucket number, or -1 if not found.
X */
Xstatic
Xfindbucket(freep, srchlen)
X union overhead *freep;
X int srchlen;
X{
X register union overhead *p;
X register int i, j;
X
X for (i = 0; i < NBUCKETS; i++) {
X j = 0;
X for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
X if (p == freep)
X return (i);
X j++;
X }
X }
X return (-1);
X}
X
X#ifdef MSTATS
X/*
X * mstats - print out statistics about malloc
X *
X * Prints two lines of numbers, one showing the length of the free list
X * for each size category, the second showing the number of mallocs -
X * frees for each size category.
X */
Xmstats(s)
X char *s;
X{
X register int i, j;
X register union overhead *p;
X int totfree = 0,
X totused = 0;
X
X Debug("Memory allocation statistics %s\nfree:\t", s);
X for (i = 0; i < NBUCKETS; i++) {
X for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
X ;
X Debug(" %d", j);
X totfree += j * (1 << (i + 3));
X }
X Debug("\nused:\t");
X for (i = 0; i < NBUCKETS; i++) {
X Debug( " %d", nmalloc[i]);
X totused += nmalloc[i] * (1 << (i + 3));
X }
X Debug("\n\tTotal in use: %d, total free: %d\n",
X totused, totfree);
X}
X#endif /* MSTATS */
X
X/* End of modified perl malloc.c */
X
Xchar *
Xcalloc(nitems, itemsz)
Xu_int nitems, itemsz;
X{
X char *cp;
X
X cp = malloc(nitems * itemsz);
X bzero(cp, nitems * itemsz);
X return cp;
X}
X
X/* These are needed for curses and other external linkage */
X
X#undef free
X
Xchar *
Xcfree(p, n, s)
Xchar *p;
Xu_int n, s;
X{
X xfree(p);
X return NULL;
X}
X
Xchar *
Xfree(p)
Xchar *p;
X{
X xfree(p);
X return NULL;
X}
X
X#else /* INTERNAL_MALLOC */
X
Xchar *stackbottom; /* set first thing in main() */
X
Xvoid
Xxfree(cp)
Xchar *cp;
X{
X extern char end[];
X
X if (cp >= end && cp < stackbottom && cp < (char *) &cp && debug < 5)
X free(cp);
X}
X
X#endif /* INTERNAL_MALLOC */
X
Xvoid
Xfree_vec(argv)
Xchar **argv;
X{
X register int n;
X if (!argv)
X return;
X for (n = 0; argv[n]; n++)
X xfree(argv[n]);
X xfree((char *)argv);
X}
END_OF_FILE
if test 10827 -ne `wc -c <'mush/malloc.c'`; then
echo shar: \"'mush/malloc.c'\" unpacked with wrong size!
fi
# end of 'mush/malloc.c'
fi
if test -f 'mush/misc_frame.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mush/misc_frame.c'\"
else
echo shar: Extracting \"'mush/misc_frame.c'\" \(7659 characters\)
sed "s/^X//" >'mush/misc_frame.c' <<'END_OF_FILE'
X/* @(#) misc_frame.c (c) copyright 9/29/89 (Dan Heller) */
X
X/*
X * This file contains several functions which create dialog box frames
X * for (currently) mail aliases and ignored headers. Each dialog box
X * has a list of some kind and a way to add or delete items from the
X * list. The list is a textsw which is updated (currently) by do_set().
X * Public routines:
X * update_list_textsw(struct options **) updates the textsw list.
X * do_alias() creates the alias dialog frame box
X * do_ignore() creates the ignored headers dialog frame box
X */
X
X#include "mush.h"
X
Xextern Notify_value fkey_interposer();
X
X/****************** Mail Aliases ********************/
X
XFrame alias_frame;
XPanel_item alias_msg, alias_name, alias_value, alias_list_textsw;
Xstatic void set_alias();
X
XFrame ignore_frame;
XPanel_item ignore_msg, ignore_name, ignore_list_textsw;
Xstatic Panel_setting set_ignore();
X
X#define MY_FRAME_WIDTH 600
X
Xstatic void
Xframe_help(item)
XPanel_item item;
X{
X (void) help(0, panel_get(item, PANEL_CLIENT_DATA), tool_help);
X}
X
Xvoid
Xupdate_list_textsw(list)
Xstruct options **list;
X{
X Textsw save = pager_textsw;
X
X if (list == &aliases)
X pager_textsw = alias_list_textsw;
X else if (list == &ignore_hdr)
X pager_textsw = ignore_list_textsw;
X else
X /* no textsw for this guy yet */
X return;
X
X if (pager_textsw && !!window_get(pager_textsw, WIN_SHOW))
X (void) do_set(*list, NULL);
X pager_textsw = save;
X}
X
Xstatic void
Xalias_done()
X{
X window_destroy(alias_frame);
X alias_frame = (Frame) 0;
X}
X
Xvoid
Xdo_aliases()
X{
X Panel panel;
X
X if (alias_frame) {
X window_set(alias_frame, WIN_SHOW, TRUE, NULL);
X return;
X }
X#ifdef SUN_3_5
X if (nopenfiles(0) < 5) {
X print("Too many frames; close one first!\n");
X return;
X }
X#endif /* SUN_3_5 */
X
X alias_frame = window_create(tool, FRAME,
X FRAME_SHOW_LABEL, TRUE,
X FRAME_LABEL, "Mail Aliases",
X FRAME_NO_CONFIRM, TRUE,
X FRAME_DONE_PROC, alias_done,
X WIN_SHOW, TRUE,
X WIN_WIDTH, MY_FRAME_WIDTH,
X NULL);
X
X panel = window_create(alias_frame, PANEL,
X PANEL_WIDTH, MY_FRAME_WIDTH,
X NULL);
X notify_interpose_event_func(panel, fkey_interposer, NOTIFY_SAFE);
X
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Help", 4, mush_font),
X PANEL_CLIENT_DATA, "aliases",
X PANEL_NOTIFY_PROC, frame_help,
X NULL);
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Set", 3, mush_font),
X PANEL_NOTIFY_PROC, set_alias,
X PANEL_CLIENT_DATA, TRUE,
X NULL);
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Unset", 5, mush_font),
X PANEL_NOTIFY_PROC, set_alias,
X PANEL_CLIENT_DATA, FALSE,
X NULL);
X
X alias_msg = panel_create_item(panel, PANEL_MESSAGE,
X PANEL_LABEL_STRING,
X "Type name of alias and address list and select <set> or <unset>",
X NULL);
X
X alias_name = panel_create_item(panel, PANEL_TEXT,
X PANEL_LABEL_STRING, "Alias Name:",
X PANEL_VALUE_DISPLAY_LENGTH, 60,
X NULL);
X alias_value = panel_create_item(panel, PANEL_TEXT,
X PANEL_LABEL_STRING, "Alias Address(es):",
X PANEL_VALUE_DISPLAY_LENGTH, 60,
X NULL);
X window_fit_height(panel);
X
X alias_list_textsw = window_create(alias_frame, TEXTSW,
X WIN_BELOW, panel,
X WIN_WIDTH, MY_FRAME_WIDTH,
X WIN_HEIGHT, 15 * l_height(),
X#ifdef SUN_4_0 /* SunOS 4.0+ */
X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_WORD,
X#else /* SUN_4_0 */
X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_CHAR,
X#endif /* SUN_4_0 */
X NULL);
X (void) notify_interpose_event_func(alias_list_textsw,
X fkey_interposer, NOTIFY_SAFE);
X
X window_fit_height(alias_frame);
X update_list_textsw(&aliases);
X}
X
Xstatic void
Xset_alias(item)
XPanel_item item;
X{
X int argc, set_it = (int)panel_get(item, PANEL_CLIENT_DATA);
X char buf[BUFSIZ], **argv, *name, *value;
X
X name = panel_get_value(alias_name);
X if (!*name) {
X panel_set(alias_msg, PANEL_LABEL_STRING, "Need an alias name.", NULL);
X return;
X }
X if (any(name, " \t")) {
X panel_set(alias_msg,
X PANEL_LABEL_STRING, "Alias name may not contain spaces.",
X NULL);
X return;
X }
X if (set_it) {
X value = panel_get_value(alias_value);
X if (!*value) {
X panel_set(alias_msg,
X PANEL_LABEL_STRING, "Specify alias address(es).",
X NULL);
X return;
X }
X sprintf(buf, "alias %s %s", name, value);
X } else
X sprintf(buf, "unalias %s", name);
X if (!(argv = mk_argv(buf, &argc, TRUE)) || do_alias(argc, argv) == -1)
X panel_set(alias_msg,
X PANEL_LABEL_STRING, "Couldn't set alias.",
X NULL);
X else
X panel_set(alias_msg,
X PANEL_LABEL_STRING, "",
X NULL);
X panel_set_value(alias_name, "");
X panel_set_value(alias_value, "");
X free_vec(argv);
X}
X
X/* int cuz it's also the callback for the text item */
Xstatic Panel_setting
Xset_ignore(item)
XPanel_item item;
X{
X int argc, set_it = (int)panel_get(item, PANEL_CLIENT_DATA);
X char buf[BUFSIZ], *name, **argv;
X
X name = panel_get_value(ignore_name);
X if (!*name) {
X panel_set(ignore_msg, PANEL_LABEL_STRING, "Missing header name.", NULL);
X return PANEL_NONE;
X }
X if (set_it)
X sprintf(buf, "ignore %s", name);
X else
X sprintf(buf, "unignore %s", name);
X /* set() will call update_list_textsw() */
X if (!(argv = mk_argv(buf, &argc, TRUE)) || set(argc, argv, NULL) == -1)
X panel_set(ignore_msg,
X PANEL_LABEL_STRING, "Internal Error!?",
X NULL);
X else
X panel_set(ignore_msg,
X PANEL_LABEL_STRING, "",
X NULL);
X free_vec(argv);
X panel_set_value(ignore_name, "");
X return PANEL_NONE;
X}
X
Xstatic void
Xignore_done()
X{
X window_destroy(ignore_frame);
X ignore_frame = (Frame) 0;
X}
X
Xvoid
Xdo_ignore()
X{
X Panel panel;
X
X if (ignore_frame) {
X window_set(ignore_frame, WIN_SHOW, TRUE, NULL);
X return;
X }
X#ifdef SUN_3_5
X if (nopenfiles(0) < 5) {
X print("Too many frames; close one first!\n");
X return;
X }
X#endif /* SUN_3_5 */
X
X ignore_frame = window_create(tool, FRAME,
X FRAME_SHOW_LABEL, TRUE,
X FRAME_LABEL, "Ignored Headers",
X FRAME_NO_CONFIRM, TRUE,
X FRAME_DONE_PROC, ignore_done,
X WIN_SHOW, TRUE,
X WIN_WIDTH, MY_FRAME_WIDTH,
X NULL);
X
X panel = window_create(ignore_frame, PANEL,
X PANEL_WIDTH, MY_FRAME_WIDTH,
X NULL);
X (void) notify_interpose_event_func(panel, fkey_interposer, NOTIFY_SAFE);
X (void) panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Help", 4, mush_font),
X PANEL_NOTIFY_PROC, frame_help,
X PANEL_CLIENT_DATA, "ignore",
X NULL);
X (void) panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Set", 3, mush_font),
X PANEL_NOTIFY_PROC, set_ignore,
X PANEL_CLIENT_DATA, TRUE,
X NULL);
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Unset", 5, mush_font),
X PANEL_NOTIFY_PROC, set_ignore,
X PANEL_CLIENT_DATA, FALSE,
X NULL);
X
X ignore_msg = panel_create_item(panel, PANEL_MESSAGE,
X PANEL_LABEL_STRING,
X "Type name of header to ignore and then <set> or <unset>",
X NULL);
X
X ignore_name = panel_create_item(panel, PANEL_TEXT,
X PANEL_LABEL_STRING, "Ignored Header:",
X PANEL_NOTIFY_PROC, set_ignore,
X PANEL_CLIENT_DATA, 1,
X PANEL_VALUE_DISPLAY_LENGTH, 60,
X NULL);
X window_fit_height(panel);
X
X ignore_list_textsw = window_create(ignore_frame, TEXTSW,
X WIN_BELOW, panel,
X WIN_WIDTH, MY_FRAME_WIDTH,
X WIN_HEIGHT, 15 * l_height(),
X#ifdef SUN_4_0 /* SunOS 4.0+ */
X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_WORD,
X#else /* SUN_4_0 */
X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_CHAR,
X#endif /* SUN_4_0 */
X NULL);
X (void) notify_interpose_event_func(ignore_list_textsw,
X fkey_interposer, NOTIFY_SAFE);
X
X window_fit_height(ignore_frame);
X update_list_textsw(&ignore_hdr);
X}
END_OF_FILE
if test 7659 -ne `wc -c <'mush/misc_frame.c'`; then
echo shar: \"'mush/misc_frame.c'\" unpacked with wrong size!
fi
# end of 'mush/misc_frame.c'
fi
if test -f 'mush/strings.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mush/strings.c'\"
else
echo shar: Extracting \"'mush/strings.c'\" \(9988 characters\)
sed "s/^X//" >'mush/strings.c' <<'END_OF_FILE'
X/* strings.c Copyright(1988) Dan Heller */
X
X#include "mush.h"
X
X/*
X * reverse a string. Useful for uucp-style address comparisons.
X */
Xchar *
Xreverse(s)
Xchar s[];
X{
X int n = strlen(s), m;
X char c;
X
X if (n < 1)
X return 0;
X if (n & 1)
X n = n/2 + 1, m = n - 2;
X else
X n /= 2, m = n - 1;
X for ( ; m >= 0; m--, n++)
X c = s[n], s[n] = s[m], s[m] = c;
X return s;
X}
X
X/*
X * lose the newline character, trailing whitespace, and return the end of p
X * test for '\n' separately since some _ctype_[] arrays may not have the
X * _S bit set for the newline character. see <ctype.h> for more info.
X */
Xchar *
Xno_newln(p)
Xregister char *p;
X{
X register char *p2 = p + strlen(p); /* point it to the null terminator */
X
X while (p2 > p && *--p2 == '\n' || isspace(*p2))
X *p2 = 0; /* get rid of newline and trailing spaces */
X return p2;
X}
X
X/* find any character in s1 that's in s2; return pointer to char in s1. */
Xchar *
Xany(s1, s2)
Xregister char *s1, *s2;
X{
X register char *p;
X if (!s1 || !*s1 || !s2 || !*s2)
X return NULL;
X for( ; *s1; s1++) {
X for(p = s2; *p; p++)
X if (*p == *s1)
X return s1;
X }
X return NULL;
X}
X
X/* check two lists of strings each of which contain substrings.
X * Each substring is delimited by any char in "delimiters"
X * return true if any elements in list1 are on list2.
X * thus:
X * string1 = "foo, bar, baz"
X * string2 = "foobar, baz, etc"
X * delimiters = ", \t"
X * example returns 1 because "baz" exists in both lists
X * NOTE: case is ignored.
X */
Xchk_two_lists(list1, list2, delimiters)
Xregister char *list1, *list2, *delimiters;
X{
X register char *p, c;
X register int found = 0;
X
X if (!list1 || !list2)
X return 0;
X
X if (p = any(list1, delimiters)) {
X if (p > list1) {
X c = *p; *p = 0;
X /* Check list2 against the first word of list1.
X * Swap places of list2 and list1 to step through list2.
X */
X found = chk_two_lists(list2, list1, delimiters);
X *p = c;
X }
X if (found)
X return 1;
X for (p++; *p && index(delimiters, *p); p++)
X ;
X if (!*p)
X return 0;
X } else if (!any(list2, delimiters))
X /* Do the trivial case of single words */
X return !lcase_strncmp(list1, list2, -1);
X else
X p = list1;
X
X /* Either only list2 has delims or the first word of list1
X * did not match anything in list2. Check list2 against the
X * rest of list1. This could be more efficient by using a
X * different function to avoid repeating the any() calls.
X */
X return chk_two_lists(list2, p, delimiters);
X}
X
Xbzero(addr, size)
Xregister char *addr;
Xregister int size;
X{
X while (size-- > 0)
X addr[size] = 0;
X}
X
X/* do an atoi() on the string passed and return in "val" the decimal value.
X * the function returns a pointer to the location in the string that is not
X * a digit.
X */
Xchar *
Xmy_atoi(p, val)
Xregister char *p;
Xregister int *val;
X{
X int positive = 1;
X
X if (!p)
X return NULL;
X *val = 0;
X if (*p == '-')
X positive = -1, p++;
X while (isdigit(*p))
X *val = (*val) * 10 + *p++ - '0';
X *val *= positive;
X return p;
X}
X
X/* strcmp ignoring case */
Xlcase_strncmp(str1, str2, n)
Xregister char *str1, *str2;
X{
X while (*str1 && *str2 && --n != 0)
X if (lower(*str1) != lower(*str2))
X break;
X else
X str1++, str2++;
X return lower(*str1) - lower(*str2);
X}
X
X/* strcpy converting everything to lower case (arbitrary) to ignore cases */
Xchar *
Xlcase_strcpy(dst, src)
Xregister char *dst, *src;
X{
X register char *s = dst;
X
X /* "lower" is a macro, don't increment its argument! */
X while (*dst++ = lower(*src))
X src++;
X return s;
X}
X
X/* this strcpy returns number of bytes copied */
XStrcpy(dst, src)
Xregister char *dst, *src;
X{
X register int n = 0;
X if (!dst || !src)
X return 0;
X while (*dst++ = *src++)
X n++;
X return n;
X}
X
Xchar *
Xsavestr(s)
Xregister char *s;
X{
X register char *p;
X
X if (!s)
X s = "";
X if (!(p = malloc((unsigned) (strlen(s) + 1)))) {
X error("out of memory saving %s", s);
X return NULL;
X }
X return strcpy(p, s);
X}
X
X/* copy a vector of strings into one string -- return the end of the string */
Xchar *
Xargv_to_string(p, argv)
Xregister char *p, **argv;
X{
X register int i;
X register char *ptr = p;
X
X *p = 0;
X if (!argv[0])
X return "";
X for (i = 0; argv[i]; i++)
X ptr += strlen(sprintf(ptr, "%s ", argv[i]));
X *--ptr = 0; /* get rid of the last space */
X return ptr;
X}
X
Xchar *
Xitoa(n)
X{
X static char buf[10];
X return sprintf(buf, "%d", n);
X}
X
X/*
X * There are two different kinds of sprintf() --those that return char * and
X * those that return int. System-V returns int (the length of the resulting
X * string). BSD has historically returned a pointer to the resulting string
X * instead. Mush was originally written under BSD, so the usage has always
X * been to assume the char * method. Because the system-v method is far more
X * useful, mush should some day change to use that method, but until then,
X * this routine was written to allow all the unix'es to appear the same to
X * the programmer regardless of which sprintf is actually used. The "latest"
X * version of 4.3BSD (as of Fall 1988) has changed its format to go from the
X * historical BSD method to the sys-v method. It is no longer possible to
X * simply #ifdef this routine for sys-v --it is now required to use this
X * routine regardless of which sprintf is notice to your machine. However,
X * if you know your system's sprintf returns a char *, you can remove the
X * define in strings.h
X */
X#include <varargs.h>
X/*VARARGS*/
X/*ARGSUSED*/
Xchar *
XSprintf(va_alist)
Xva_dcl
X{
X char *buf, *fmt;
X va_list ap;
X
X va_start(ap);
X buf = va_arg(ap, char *);
X fmt = va_arg(ap, char *);
X#ifdef VPRINTF
X (void) vsprintf(buf, fmt, ap);
X#else
X {
X FILE foo;
X foo._cnt = BUFSIZ;
X foo._base = foo._ptr = buf; /* may have to be cast (unsigned char *) */
X foo._flag = _IOWRT+_IOSTRG;
X (void) _doprnt(fmt, ap, &foo);
X *foo._ptr = '\0'; /* plant terminating null character */
X }
X#endif /* VPRINTF */
X va_end(ap);
X return buf;
X}
X
Xvoid
Xprint_argv(argv)
Xchar **argv;
X{
X while (*argv)
X if (debug)
X wprint("(%s) ", *argv++);
X else
X wprint("%s ", *argv++);
X wprint("\n");
X}
X
X/*
X * putstring -- put a string into a file. Expand \t's into tabs and \n's
X * into newlines. Append a \n and fflush(fp);
X */
Xvoid
Xputstring(p, fp)
Xregister char *p;
Xregister FILE *fp;
X{
X for ( ; *p; ++p)
X if (*p != '\\')
X (void) fputc(*p, fp);
X else
X switch(*++p) {
X case 'n': (void) fputc('\n', fp);
X when 't': (void) fputc('\t', fp);
X otherwise: (void) fputc(*p, fp);
X }
X (void) fputc('\n', fp);
X (void) fflush(fp);
X}
X
X#define chtoi(c) ((int)(c) - (int)'0')
X
X/* m_xlate(str) converts strings of chars which contain ascii representations
X * of control characters appearing in str into the literal characters they
X * represent. The usual curses-mode character expansions (\Cx -> control-x)
X * are honored, as are most C escapes. Unrecognized portions are unchanged.
X */
Xchar *
Xm_xlate (str)
Xregister char *str;
X{
X register char *r, *s, *t;
X int dv, nd;
X
X /*
X * r will receive the new string, s will track the old one,
X * and t will step through escape sequences
X * This allows the translation to be done in place
X */
X r = s = str;
X while (s && *s) {
X if (*s == '\\') {
X t = s + 1;
X /*
X * After each case below, t should point to the character
X * following the escape sequence
X */
X switch(*t) {
X case '\0' :
X /*
X * Hmmm ... a backslash followed by the string
X * terminator. Copy the backslash ONLY.
X */
X *r++ = *s++;
X break;
X case '0' :
X case '1' :
X case '2' :
X case '3' :
X case '4' :
X case '5' :
X case '6' :
X case '7' :
X /*
X * Convert up to 3 octal digits to their ascii value
X */
X dv = chtoi(*t++);
X for (nd = 0; (isdigit(*t) && (nd < 2)); nd++)
X if (chtoi(*t) < 8)
X dv = (8 * dv) + chtoi(*t++);
X else
X break;
X if (dv < 256 && dv > 0)
X /* Valid octal number escaped */
X *r++ = (char)dv;
X else
X /* Invalid octal number, so copy unchanged */
X while (s < t)
X *r++ = *s++;
X break;
X case 'b' :
X *r++ = '\b';
X t++;
X break;
X case 'C' :
X t++;
X if (*t == '?')
X *r++ = '\177';
X else if (*t == '~')
X *r++ = '\036';
X else if (*t == '/')
X *r++ = '\037';
X else if (isalpha(*t) || *t > '\132' && *t < '\140')
X *r++ = *t & 037;
X else
X while (s <= t) *r++ = *s++;
X t++;
X break;
X case 'E' :
X *r++ = '\033';
X t++;
X break;
X case 'f' :
X *r++ = '\f';
X t++;
X break;
X case 'n' :
X *r++ = '\n';
X t++;
X break;
X case 'r' :
X *r++ = '\r';
X t++;
X break;
X case 't' :
X *r++ = '\t';
X t++;
X break;
X case '\\' :
X *r++ = *t++;
X break;
X default :
X /*
X * Not recognized, so copy both characters
X */
X *r++ = *s++;
X *r++ = *s++;
X break;
X }
X /*
X * Now make sure s also points to the character after the
X * escape sequence, by comparing to t
X */
X if (t > s)
X s = t;
X } else
X *r++ = *s++;
X }
X *r = '\0';
X return str;
X}
X
X/*
X * Convert control characters to ascii format (reverse effect of m_xlate()).
X */
Xchar *
Xctrl_strcpy(s_out, s_in, bind_format)
Xregister char *s_out, *s_in;
X{
X#if !defined(M_XENIX) || (defined(M_XENIX) && !defined(CURSES))
X extern char *_unctrl[];
X#endif /* !M_XENIX || M_XENIX && !CURSES */
X char *start = s_out;
X
X for (; *s_in; s_in++)
X if (*s_in == '\n')
X *s_out++ = '\\', *s_out++ = 'n';
X else if (*s_in == '\r')
X *s_out++ = '\\', *s_out++ = 'r';
X else if (*s_in == '\t')
X *s_out++ = '\\', *s_out++ = 't';
X else if (*s_in == ESC)
X *s_out++ = '\\', *s_out++ = 'E';
X else if (iscntrl(*s_in)) {
X if (bind_format)
X *s_out++ = '\\', *s_out++ = 'C';
X else
X *s_out++ = '^';
X *s_out++ = _unctrl[*s_in][1];
X } else
X *s_out++ = *s_in;
X *s_out = 0;
X return start;
X}
END_OF_FILE
if test 9988 -ne `wc -c <'mush/strings.c'`; then
echo shar: \"'mush/strings.c'\" unpacked with wrong size!
fi
# end of 'mush/strings.c'
fi
echo shar: End of archive 17 \(of 19\).
cp /dev/null ark17isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 19 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