home *** CD-ROM | disk | FTP | other *** search
- /* @(#)hdr_sw.c (c) copyright 2/17/90 (Dan Heller) */
-
- /* This file handles all the header subwindow code. It would be much
- * better if this subwindow, which displays the headers for the current
- * folder, were a textsw. That way, this file would go away completely.
- * Until then, we have to create the window (canvas), define an event
- * handler for when events happen in this window, create our own scrollbar,
- * figure out when the user scrolls with it, attach our own popup menu to
- * the canvas, handle events for that, let's see... kitchen sink? Oh,
- * that's over there in the corner.
- */
- #include "mush.h"
- #ifdef SUN_4_0 /* SunOS 4.0+ */
- #include <sunwindow/win_keymap.h>
- #endif /* SUN_4_0 */
-
- extern Panel hdr_panel;
- extern void hdr_io(), fkey_interposer();
-
- static Notify_value scroll_hdr();
- static void msg_menu_func(), do_menu(), msg_menu_notify();
- static Menu msg_menu;
- static Menu_item cur_msg_item;
-
- void
- make_hdr_sw(parent)
- Frame parent;
- {
- Textsw tmpsw;
-
- if (!(hdr_sw = window_create(parent, CANVAS,
- WIN_HEIGHT, 10 + screen*l_height(),
- WIN_WIDTH, WIN_EXTEND_TO_EDGE,
- WIN_BELOW, hdr_panel,
- WIN_EVENT_PROC, hdr_io,
- CANVAS_AUTO_CLEAR, TRUE,
- CANVAS_RETAINED, TRUE,
- WIN_CONSUME_KBD_EVENTS,
- WIN_ASCII_EVENTS, WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, NULL,
- WIN_IGNORE_KBD_EVENTS,
- WIN_UP_ASCII_EVENTS, NULL,
- WIN_CONSUME_PICK_EVENTS,
- LOC_WINENTER, WIN_MOUSE_BUTTONS, LOC_MOVE, NULL,
- WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
- NULL)))
- perror("hdr_sw"), cleanup(0);
- hdr_win = canvas_pixwin(hdr_sw);
- (void) notify_interpose_event_func(hdr_sw, fkey_interposer, NOTIFY_SAFE);
- (void) notify_interpose_event_func(hdr_sw, scroll_hdr, NOTIFY_SAFE);
- scrollbar_set((Scrollbar)window_get(hdr_sw, WIN_VERTICAL_SCROLLBAR),
- SCROLL_NORMALIZE, FALSE,
- SCROLL_ADVANCED_MODE, TRUE,
- SCROLL_LINE_HEIGHT, l_height(),
- SCROLL_VIEW_LENGTH, screen,
- NULL);
- #ifdef SUN_4_0 /* SunOS 4.0+ */
- /* This is a particularly ugly hack. If Sun only documented the correct
- * way to set up the key mapping for a window the way that textsw's do
- * then we wouldn't have to do anything this awful. Maybe in 4.2.....
- *
- * The object here is to get the same translation table for our header
- * canvas as for a textsw (more or less anyway). This way the arrow
- * keys and such work right.
- */
- tmpsw = window_create(parent, TEXTSW, NULL);
- #ifdef SUN_4_1
- keymap_from_fd[(int)window_get(hdr_sw, WIN_FD)].keymap =
- keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].keymap;
- keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].keymap = (Keymap *) 0;
- #else /* !SUN_4_1 */
- keymap_from_fd[(int)window_get(hdr_sw, WIN_FD)].kf_keymap =
- keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].kf_keymap;
- keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].kf_keymap = (Keymap *) 0;
- #endif /* SUN_4_1 */
- (void) window_destroy(tmpsw);
- #endif /* SUN_4_0 */
- }
-
- static Notify_value
- scroll_hdr(canvas, event, arg, type)
- Canvas canvas;
- Event *event;
- Notify_arg arg;
- Notify_event_type type;
- {
- int amount, count, i;
- int show_deleted = !!do_set(set_options, "show_deleted");
- char *argv[3], msgnum[8];
- Scrollbar sb;
- argv[0] = "headers";
- argv[1] = msgnum;
- argv[2] = NULL;
-
- switch (decode_scroll((Notify_client) canvas, event, screen, &amount)) {
- case MUSH_SCROLL_PASS_EVENT:
- switch(ID) {
- case SCROLL_ENTER:
- case SCROLL_EXIT:
- return NOTIFY_IGNORED;
- case SCROLL_REQUEST:
- sb = (Scrollbar)arg;
- switch( (Scroll_motion)
- scrollbar_get(sb, SCROLL_REQUEST_MOTION)) {
- case SCROLL_LINE_FORWARD:
- amount = 1;
- break;
- case SCROLL_LINE_BACKWARD:
- amount = -1;
- break;
- case SCROLL_ABSOLUTE:
- i = (int)scrollbar_get(sb, SCROLL_VIEW_START);
- if (!show_deleted) {
- count = i;
- for (i = 0; i < msg_cnt-1; i++)
- if (!ison(msg[i].m_flags, DELETE) &&
- count-- == 0)
- break;
- }
- (void) sprintf(msgnum, "%d", i+1);
- argv[1] = msgnum;
- (void) do_hdrs(2, argv, NULL);
- return(NOTIFY_DONE);
- default:
- amount =
- (int)scrollbar_get(sb, SCROLL_VIEW_START) -
- (int)scrollbar_get(sb, SCROLL_LAST_VIEW_START);
- break;
- }
- break;
- default:
- return notify_next_event_func(canvas, event, arg, type);
- }
- break;
- case MUSH_SCROLL_IGNORE:
- return NOTIFY_IGNORED;
- case MUSH_SCROLL_TO:
- if (amount == 1) {
- argv[1] = "1";
- (void) do_hdrs(2, argv, NULL);
- return NOTIFY_DONE;
- } else {
- (void) sprintf(msgnum, "%d", msg_cnt - screen + 1);
- argv[1] = msgnum;
- (void) do_hdrs(2, argv, NULL);
- return NOTIFY_DONE;
- }
- }
- if (amount == screen)
- argv[1] = "+";
- else if (amount == -screen)
- argv[1] = "-";
- else if (amount >= 0) {
- if (amount < screen)
- (void) sprintf(msgnum, "%d", min(n_array[amount]+1, msg_cnt-1));
- else {
- /* so much for layering */
- for (i = n_array[0]+1; i < msg_cnt-1 && amount > 0; i++)
- if (show_deleted || !ison(msg[i].m_flags, DELETE))
- amount--;
- (void) sprintf(msgnum, "%d", i);
- }
- } else {
- /* so much for layering */
- for (i = n_array[0]; i > 0 && amount < 0; i--)
- if (show_deleted || !ison(msg[i-1].m_flags, DELETE))
- amount++;
- (void) sprintf(msgnum, "%d", i + 1);
- }
- (void) do_hdrs(2, argv, NULL);
- return NOTIFY_DONE;
- }
-
- /*
- * Routines to handle io on the hdr_sw (canvas).
- */
-
- /* if MENU button goes down on a hdr, drawbox around hdr and popup menu */
- #define draw(x1,y1,x2,y2) (void) pw_vector(hdr_win, x1,y1,x2,y2,PIX_XOR,1)
- #define box(x1,y1,x2,y2) \
- draw(x1,y1, x1,y2), draw(x1,y2, x2,y2), \
- draw(x2,y2, x2,y1), draw(x2,y1, x1,y1)
-
- #define READ_MSG (char *)'r'
- #define DEL_MSG (char *)'d'
- #define UNDEL_MSG (char *)'u'
- #define REPL_MSG (char *)'R'
- #define SAVE_MSG (char *)'s'
- #define PRNT_MSG (char *)'p'
- #define PRE_MSG (char *)'P'
- #define HELP_MSG (char *)'H'
-
- /*ARGSUSED*/
- void
- hdr_io(canvas, event, arg)
- Canvas canvas;
- Event *event;
- caddr_t arg;
- {
- static int which_cursor;
- int line;
-
- if (ID == WIN_REPAINT) {
- if (is_iconic != (int) window_get(tool, FRAME_CLOSED)) {
- check_new_mail();
-
- /* Reload time with value of timeout upon timer expiration. */
- mail_timer.it_interval.tv_sec = time_out;
-
- mail_timer.it_value.tv_sec = time_out;
- (void) notify_set_itimer_func(tool, do_check,
- ITIMER_REAL, &mail_timer, (struct itimerval *) 0);
- is_iconic = 0;
- }
- }
-
- /* make cursor change which button is lit */
- switch (which_cursor) {
- case 0 : (void) window_set(canvas, WIN_CURSOR, l_cursor, NULL);
- when 1 : (void) window_set(canvas, WIN_CURSOR, m_cursor, NULL);
- when 2 : (void) window_set(canvas, WIN_CURSOR, r_cursor, NULL);
- }
-
- which_cursor = (which_cursor+1) % 3;
-
- /* just return -- we just wanted to make the cursor flicker */
- if (ID == LOC_STILL || ID == LOC_MOVE || ID == LOC_WINENTER ||
- ID == LOC_RGNENTER || ID == KBD_USE || ID == KBD_DONE)
- return;
-
- if (event_is_button(event) && event_is_down(event)) {
- line = (event_y(event) - 5) / l_height();
- if (line < 0)
- line = 0;
- else if (line >= screen)
- line = screen - 1;
- if (!msg_cnt || n_array[line] > msg_cnt)
- return;
- if (ID == MS_RIGHT)
- do_menu(hdr_sw, event, window_get(hdr_sw, WIN_FD), n_array[line]);
- else if (ID == MS_MIDDLE) {
- set_isread(n_array[line]);
- msg_menu_func(DEL_MSG, n_array[line]);
- } else {
- int do_do_hdrs = 0;
- if (current_msg != n_array[line]) {
- current_msg = n_array[line];
- do_do_hdrs++;
- }
- if (ison(msg[current_msg].m_flags, UNREAD))
- do_do_hdrs++;
- (void) display_msg(n_array[line], (u_long)0);
- if (do_do_hdrs)
- (void) do_hdrs(0, DUBL_NULL, NULL);
- }
- } else
- window_default_event_proc(canvas, event, NULL);
- }
-
- static struct menu_rec {
- char *str; /* Menu item label. */
- char *data; /* Menu item client data. */
- };
-
- static void
- get_msg_menu()
- {
- int i;
- Menu_item mi = NULL;
-
- static struct menu_rec msg_items[] = {
- { "Read", READ_MSG },
- { "Delete", DEL_MSG },
- { "Undelete", UNDEL_MSG },
- { "Reply", REPL_MSG },
- { "Save", SAVE_MSG },
- { "Preserve", PRE_MSG },
- { "Print", PRNT_MSG },
- { "Help", HELP_MSG },
- };
-
- msg_menu = menu_create(MENU_NOTIFY_PROC, msg_menu_notify, NULL);
- for (i = 0; i < ArraySize(msg_items); i++) {
- mi = menu_create_item(MENU_STRING, msg_items[i].str,
- MENU_CLIENT_DATA, msg_items[i].data,
- NULL);
- (void) menu_set(msg_menu, MENU_APPEND_ITEM, mi, NULL);
- }
- }
-
- static void
- msg_menu_notify(menu, item)
- Menu menu;
- Menu_item item;
- {
- cur_msg_item = item;
- }
-
- static void
- do_menu(can_sw, event, fd, message)
- Canvas can_sw;
- Event *event;
- int fd, message;
- {
- char *action;
- static char buf[16];
-
- if (!msg_cnt) {
- wprint("No Messages.\n");
- return;
- }
- if (fd) {
- int line;
- Rect *hdr_rect;
-
- if (!msg_menu)
- get_msg_menu();
- (void) sprintf(buf, "Message #%d", message+1);
- /* provide feedback about what message the menu references */
- for (line = 0; line <= n_array[screen-1]; line++)
- if (n_array[line] == message)
- break;
- hdr_rect = (Rect *)window_get(hdr_sw, WIN_RECT);
- box(0, 5 + line * l_height(),
- hdr_rect->r_width, 5 + (line+1) * l_height());
- /* show menu */
- menu_show(msg_menu, can_sw, event, NULL);
- /* remove feedback */
- box(0, 5 + line * l_height(),
- hdr_rect->r_width, 5 + (line+1) * l_height());
- /* if user selected something, figure out what was selected. */
- if (!cur_msg_item)
- return;
- action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA);
- cur_msg_item = (Menu_item)NULL;
- } else
- action = (char *) event;
-
- set_isread(message);
- switch ((int) action) {
- case SAVE_MSG : {
- extern Panel_item msg_num_item, save_item;
- (void) panel_set(msg_num_item, PANEL_VALUE,
- sprintf(buf, "%d", message+1), NULL);
- event_id(event) = MS_LEFT;
- do_file_dir(save_item, 0, event);
- (void) panel_set(msg_num_item, PANEL_VALUE, NO_STRING, NULL);
- }
- when HELP_MSG :
- help(0, "headers", tool_help);
- when PRNT_MSG : case PRE_MSG : case UNDEL_MSG : case DEL_MSG :
- msg_menu_func(action, message);
- when REPL_MSG : {
- extern Panel_item reply_item;
- (void) open_compose();
- /* reply_item shouldn't be here */
- respond_mail(reply_item, message, NO_EVENT);
- }
- otherwise :
- if (current_msg != message) {
- current_msg = message;
- (void) do_hdrs(0, DUBL_NULL, NULL);
- }
- #ifdef SUN_3_5
- /* Test for a shortage of file descriptors */
- if (nopenfiles(0) > 3)
- #endif /* SUN_3_5 */
- turnon(glob_flags, NEW_FRAME);
- more_prompt = compose_hdr(message);
- display_msg(message, (u_long)0);
- }
- }
-
- /* msg_menu_func() is a function called to perform message menu actions
- * that are either selected from the popup menu in the header window or
- * from mouse actions that function as accelerators.
- */
- static void
- msg_menu_func(action, message)
- char *action;
- {
- int argc;
- register char **argv;
- char buf[32];
-
- wprint("Message #%d ", message+1);
- if (action == UNDEL_MSG || action == DEL_MSG)
- wprint("%sd.\n", sprintf(buf, "%selete",
- (action == DEL_MSG)? "d": "und"));
- else if (action == PRNT_MSG) {
- wprint("sent to printer.\n");
- (void) strcpy(buf, "lpr");
- } else if (action == PRE_MSG)
- wprint("%sd.\n", strcpy(buf, "preserve"));
- (void) sprintf(&buf[strlen(buf)], " %d", message+1);
-
- if (argv = make_command(buf, (char ***) DUBL_NULL, &argc))
- (void) do_command(argc, argv, msg_list);
- }
-