home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume18
/
mush6.4
/
part06
/
select.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-03-12
|
13KB
|
429 lines
/* select.c (c) copyright 1986 (Dan Heller) */
/*
* Routine which handle io (selection on file descriptors) between user and
* the various windows.
*
* In toolmode, the user types characters and each character is interpreted
* here and, if applicable, is sent to rite.c where it is appended to a
* string similar to a tty driver and fgets. When the user types a '\n' the
* rite() routine returns the string and we call add_to_letter to append the
* string to the letter. Signals are caught here as well. that is the signal
* characters setup by the user are checked and if one matches, call the signal
* handling routine as if there were a real signal.
*
* Mouse handling is done here. See code for more detail.
*/
#include "mush.h"
#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 E_EDIT (char *)'e'
#define E_VIEW (char *)'v'
#define E_INCLUDE (char *)'i'
#define E_SEND (char *)'S'
#define E_ABORT (char *)'a'
#define MENU_HELP (char *)'h'
#define O_SAVE (char *)'s'
#define O_QUIT (char *)'q'
#define O_RSTR (char *)'r'
#define N_MENU_ITEMS 8
#define E_MENU_ITEMS 6
msg_io(gfxsw, ibits, obits, ebits, timer)
register struct gfxsubwindow *gfxsw;
register int *ibits,*obits,*ebits;
struct timeval **timer;
{
register char *p;
struct inputevent event;
static char lastchar;
static int line, count;
if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
*ibits = *obits = *ebits = 0;
return;
}
if (input_readevent(msg_sw->ts_windowfd, &event) == -1) {
error("input event");
return;
}
/*
if (ID == LOC_WINENTER) {
int x;
struct inputmask im;
win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
}
*/
if (ID >= KEY_LEFTFIRST)
if (ison(glob_flags, IS_GETTING))
print("Finish editing letter first");
else
(void) func_key(ID);
else if (isascii(ID) && (msg_pix || ison(glob_flags, IS_GETTING) ||
getting_opts)) {
if (getting_opts) {
/*
* txt.x <= 5 indicates not to accept typed input for options
* and function key setting.
*/
if (txt.x > 5) {
/* ^C, ^\ or ^U kills line */
type_cursor(PIX_XOR);
if (ID == tchars.t_intrc || ID == tchars.t_quitc ||
ID == _tty.sg_kill) {
rite(_tty.sg_kill), txt.x = 5;
if (getting_opts == 1)
option_line(line), display_opts(0);
else
set_key(0, 0, 0);
} else if (p = rite((char)ID)) {
/* if no string entered, preserve old value */
if (*p && getting_opts == 1)
add_opt(p, line);
if (getting_opts == 2)
set_key(p, 0,0);
} else
type_cursor(PIX_XOR);
}
}
/*
* This section MUST BE BEFORE the following "is_getting" section.
* If user displays a message while editing a letter, he must hit 'q'
* to return to edit mode. He may not edit a new letter while one is
* already being edited.
*/
else if (msg_pix)
if (isdigit(ID)) {
if (!isdigit(lastchar))
count = 0;
count = count * 10 + ID - '0';
} else {
/* scroll <count> lines */
if (!count)
count = 1;
if (ID == 'k' || ID == 'K' || ID == '-')
scroll_win(-count);
else if (ID == '\n' || ID == '\r' || ID == 'j' ||
ID == 'J' || ID == '+')
scroll_win(count);
else if (ID == ' ')
scroll_win(crt-3);
else if ((ID == 'q' || ID == 'Q') &&
ison(glob_flags, IS_GETTING)) {
pr_destroy(msg_pix), msg_pix = (struct pixrect *)NULL;
win_setcursor(msg_sw->ts_windowfd, &write_cursor);
txt.x = 5, txt.y = msg_rect.r_height - l_height(curfont);
wprint("\n(continue editing letter)\n");
clr_bot_line();
type_cursor(PIX_SRC);
}
}
/*
* If msg_pix is NULL, then we are not reading a message. If we are
* editing a letter, then enter the keys typed. If we are doing
* nothing, ignore this input.
*/
else if (ison(glob_flags, IS_GETTING)) {
type_cursor(PIX_XOR);
if (lastchar != ltchars.t_lnextc &&
(ID == tchars.t_intrc || ID == tchars.t_quitc)) {
(void) rite(_tty.sg_kill);
(void) rm_edfile(SIGINT);
} else {
register int n = 1;
if (ID == tchars.t_eofc && txt.x == 5
|| (p = rite((char)ID)) && !(n = add_to_letter(p)))
finish_up_letter();
else if (n > 0)
type_cursor(PIX_XOR);
}
}
lastchar = ID;
} else switch(ID) {
when MS_LEFT : case MS_MIDDLE:
if (getting_opts == 2)
if (ID == MS_LEFT)
set_key(NULL, event.ie_locx, event.ie_locy);
else {
register char *p = find_key(event.ie_locx, event.ie_locy);
if (p)
print("Function key %s: %s", p, key_set_to(p));
}
else if (getting_opts) {
int y = event.ie_locy - 50;
if (y < -24)
break;
if (y < 0) {
register int x = event.ie_locx;
register int X = 60*l_width(LARGE);
if (x >= X && x <= X+16)
display_opts(-1); /* scroll options back one value */
else if (x >= X+20 && x <= X+36)
display_opts(1); /* scroll options forward one value */
break;
}
/* the user was typing something -- stopped by using mouse */
if (txt.x > 5) {
type_cursor(PIX_CLR);
(void) rite(_tty.sg_kill), txt.x = 5;
option_line(line), display_opts(0);
}
line = y/20;
if (ID == MS_LEFT)
toggle_opt(line);
help_opt(line); /* display help (short info) in both cases */
} else if (msg_pix)
if (ID == MS_LEFT)
scroll_win(crt-3);
else
scroll_win(-(crt-3));
when MS_RIGHT:
if (getting_opts)
(void) view_opts_menu(&event, gfxsw->gfx_windowfd);
else if (isoff(glob_flags, IS_GETTING))
(void) do_menu(&event, gfxsw->gfx_windowfd, current_msg);
else
(void) edit_menu(&event, gfxsw->gfx_windowfd);
otherwise: ;
}
*ibits = *obits = *ebits = 0;
}
struct cursor *mice[3] = { &l_cursor, &m_cursor, &r_cursor };
hdr_io(gfxsw, ibits, obits, ebits, sw_timer)
register struct gfxsubwindow *gfxsw;
int *ibits,*obits,*ebits;
struct timeval **sw_timer;
{
static int which_cursor;
struct inputmask im;
struct inputevent event;
int line;
if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
*ibits = *obits = *ebits = 0;
return;
}
/* make curosr change which button is lit */
win_setcursor(gfxsw->gfx_windowfd, mice[which_cursor]);
which_cursor = (which_cursor+1) % 3;
if (input_readevent(hdr_sw->ts_windowfd, &event) == -1) {
error("input event");
return;
}
/* I'm not sure why I have to do this.
* I'm doing it because sometimes the IO hangs completely and no input
* is accepted. What I do here is get the current mask, save it, then
* reset it. This action seems to flush the IO queue, and I don't have hung
* IO anymore. This shouldn't be necessary, but it appears to work.
* (occurances have droped about 90%)
*/
if (ID == LOC_WINENTER) {
int x;
win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
}
/* just return -- we just wanted to make the cursor flicker */
if (ID == LOC_STILL || ID == LOC_MOVE || ID == LOC_WINENTER) {
*ibits = *obits = *ebits = 0;
return;
}
line = event.ie_locy / l_height(DEFAULT);
if (ID >= KEY_LEFTFIRST)
(void) func_key(ID);
else if (n_array[line] > msg_cnt)
if (!msg_cnt)
print("-- You have no messages -- ");
else
print("Message out of range. Place mouse over a legal message.");
else switch(ID) {
when MS_LEFT: case MS_MIDDLE:
(void) do_menu((ID == MS_LEFT)? READ_MSG: DEL_MSG, 0,n_array[line]);
when MS_RIGHT:
(void) do_menu(&event, gfxsw->gfx_windowfd, n_array[line]);
otherwise : print("Unkown ID = %d", ID);
}
*ibits = *obits = *ebits = 0;
}
/* if "fd" is 0, then event points to the action to be taken.
* otherwise, determine action to be taken by displaying a menu.
* message is the number current_msg should be changed to (may be the same).
*/
do_menu(event, fd, message)
caddr_t event;
{
static char buf[20];
struct menuitem *m_item;
char *action;
static struct menuitem msg_menu_items[] = {
{ MENU_IMAGESTRING, "Read", READ_MSG },
{ MENU_IMAGESTRING, "Delete", DEL_MSG },
{ MENU_IMAGESTRING, "Undelete", UNDEL_MSG },
{ MENU_IMAGESTRING, "Reply", REPL_MSG },
{ MENU_IMAGESTRING, "Save", SAVE_MSG },
{ MENU_IMAGESTRING, "Preserve", PRE_MSG },
{ MENU_IMAGESTRING, "Print", PRNT_MSG },
{ MENU_IMAGESTRING, "Help", MENU_HELP }
};
static struct menu help_menu = {
MENU_IMAGESTRING, "Item Help",
N_MENU_ITEMS, msg_menu_items,
(struct menu *)NULL, NULL
};
static struct menu msgs_menu = {
MENU_IMAGESTRING, buf, N_MENU_ITEMS,
msg_menu_items, &help_menu, NULL
};
/* to have the menu stack maintain order of menus upon each invokation,
* declare menu_ptr to be static and remove the following two lines
* after the declaration.
*/
struct menu *menu_ptr = &msgs_menu;
msgs_menu.m_next = &help_menu;
help_menu.m_next = (struct menu *)NULL;
if (!msg_cnt) {
print("No Messages.");
return;
}
if (fd) {
(void) sprintf(buf, "Message #%d", message+1);
if (m_item = menu_display(&menu_ptr, (struct inputevent *)event, fd))
action = m_item->mi_data;
else
return;
} else
action = event;
if (menu_ptr == &help_menu || action == MENU_HELP) {
switch(action) {
when DEL_MSG: case UNDEL_MSG:
(void) help(fd, "menu_delete", tool_help);
when READ_MSG: (void) help(fd, "next", tool_help);
when REPL_MSG: (void) help(fd, "menu_respond", tool_help);
when SAVE_MSG: (void) help(fd, "save", tool_help);
when PRE_MSG: (void) help(fd, "preserve", tool_help);
when PRNT_MSG: (void) help(fd, "printer", tool_help);
when MENU_HELP:
if (menu_ptr == &help_menu)
(void) help(fd, "help_menu_help_msg", tool_help);
else
(void) help(fd, "msg_menu", tool_help);
}
return;
}
set_isread(message);
if (action == SAVE_MSG) {
panel_set(msg_num_item, PANEL_VALUE, sprintf(buf, "%d", message+1), 0);
((struct inputevent *)event)->ie_code = MS_LEFT;
do_file_dir(save_item, 0, event);
panel_set(msg_num_item, PANEL_VALUE, NO_STRING, 0);
return;
} else if (action == PRNT_MSG || action == PRE_MSG ||
action == UNDEL_MSG || action == DEL_MSG) {
fkey_misc(action, message);
return;
}
if (isoff(glob_flags, IS_GETTING)) {
current_msg = message;
(void) do_hdrs(0, DUBL_NULL, NULL);
}
if (action == REPL_MSG) {
respond_mail(respond_item, 0, event);
return;
} else if (ison(glob_flags, IS_GETTING)) {
if (exec_pid)
/* User can read a message as long as he's not in an editor */
print("Finish editing message first");
else {
(void) do_hdrs(0, DUBL_NULL, NULL);
display_msg(message, (long)0);
}
return;
}
display_msg(current_msg, (long)0);
}
/* miscellaneous function key actions there are here because the defines
* for DEL_MSG, etc are here in this file and the function is called from
* here more often.
*/
fkey_misc(action, message)
char *action;
{
int argc;
register char **argv;
char buf[30];
print("Message #%d ", message+1);
if (action == UNDEL_MSG || action == DEL_MSG)
print_more("%sd. ", sprintf(buf, "%selete",
(action == DEL_MSG)? "d": "und"));
else if (action == PRNT_MSG) {
print_more("sent to printer");
(void) strcpy(buf, "lpr");
} else if (action == PRE_MSG)
print_more("%sd", strcpy(buf, "preserve"));
(void) sprintf(&buf[strlen(buf)], " %d", message+1);
if (message == current_msg && action == DEL_MSG)
do_clear();
if (argv = make_command(buf, DUBL_NULL, &argc))
(void) do_command(argc, argv, msg_list);
return;
}
view_opts_menu(event, fd)
struct inputevent *event;
{
static char buf[5];
struct menuitem *m_item;
char *action;
static struct menuitem opts_items[] = {
{ MENU_IMAGESTRING, "Save Options", O_SAVE },
{ MENU_IMAGESTRING, "Restore Options", O_RSTR },
{ MENU_IMAGESTRING, "Quit Options", O_QUIT },
{ MENU_IMAGESTRING, "Help", MENU_HELP }
};
static struct menu msgs_menu = {
MENU_IMAGESTRING, "Options", 4, opts_items, (struct menu *)NULL, NULL
};
struct menu *menu_ptr = &msgs_menu;
if (m_item = menu_display(&menu_ptr, event, fd))
action = m_item->mi_data;
else
return;
switch(action) {
case O_SAVE:
save_opts(0, DUBL_NULL);
when O_RSTR:
init();
if (getting_opts == 1)
view_options();
else
set_fkeys();
when O_QUIT:
do_clear();
unlock_cursors(); /* actually resets msg_win's cursor */
if (isoff(glob_flags, IS_GETTING) && msg_cnt)
if (isoff(msg[current_msg].m_flags, DELETE))
display_msg(current_msg, (long)0);
else
(void) read_mail(NO_ITEM, 0, NO_EVENT);
when MENU_HELP:
(void) help(fd, (getting_opts == 1)? "options": "fkeys", tool_help);
}
}