home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.freefriends.org
/
ftp.freefriends.org.tar
/
ftp.freefriends.org
/
arnold
/
Source
/
mush.rstevens.tar.gz
/
mush.tar
/
tooledit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-03
|
9KB
|
318 lines
/* @(#)tooledit.c (c) copyright 2/14/90 (Dan Heller) */
/*
* intercept events in the compose window for auto-
* positioning and tilde command recognition.
*/
#include "mush.h"
static short dat_bentarrow[] = {
0x007F, 0x007F, 0x007F, 0x0007, 0x0407, 0x0C07, 0x1C07, 0x3807,
0x7FFF, 0xFFFF, 0x7FFF, 0x3800, 0x1C00, 0x0C00, 0x0400, 0x0000
};
mpr_static(bent_arrow, 16, 16, 1, dat_bentarrow);
Cursor bentarrow;
extern void do_send(), do_edit();
/* Return the byte position in the textsw of the header specified */
Textsw_index
header_position(textsw, str)
Textsw textsw;
char *str;
{
char buf[256];
register char *p = buf, *p2;
int contd_hdr = 0, add_newline = 0;
Textsw_index pos = 0L, ret_pos = 0L;
buf[0] = 0;
for (;;) {
/* get a line at a time from the textsw */
(void) window_get(textsw, TEXTSW_CONTENTS, pos, buf, 256);
if (p = index(buf, '\n'))
*p = 0;
else
add_newline++;
p = buf;
skipspaces(0);
if (!*p) /* newline alone -- end of headers */
break;
pos += strlen(buf) + 1; /* advance position to next line */
if (*p != ' ' && *p != '\t') {
contd_hdr = 0;
/* strcmp ignoring case */
for (p2 = str; *p && *p2 && lower(*p2) == lower(*p); ++p, ++p2)
;
/* MATCH is true if p2 is at the end of str and *p is ':' */
if (*p2 || *p != ':') {
if (!*p2 && isspace(*any(p, ": \t"))) {
/* Not a legal or continued header */
pos -= strlen(buf) + 1; /* go back to beginning of line */
break;
}
continue;
} else {
contd_hdr = 1;
ret_pos = pos - 1;
}
} else if (!contd_hdr)
continue;
}
if (!ret_pos) {
/* coudn't find the header -- add it */
window_set(textsw, TEXTSW_INSERTION_POINT, pos, NULL);
p = buf;
if (add_newline)
*p++ = '\n', pos--;
for (p2 = str; *p2; ++p2) {
if (p2 == str || p2[-1] == '-')
*p++ = upper(*p2);
else
*p++ = *p2;
}
*p++ = ':', *p++ = ' ', *p++ = '\n', *p = 0;
textsw_insert(textsw, buf, strlen(buf));
ret_pos = pos + strlen(buf) - 1;
}
return ret_pos;
}
/* position_flags indicates which header to go to when uses tilde commands */
static u_long position_flags;
static char *tilde_hdrs[] = {
#define POSITION_TO ULBIT(0)
"to",
#define POSITION_SUBJ ULBIT(1)
"subject",
#define POSITION_CC ULBIT(2)
"cc",
#define POSITION_BCC ULBIT(3)
"bcc",
#define POSITION_FCC ULBIT(4)
"fcc"
};
#define POSITION_ALL \
((POSITION_TO) | (POSITION_SUBJ) | (POSITION_CC) | (POSITION_BCC))
#define POSITION_END ULBIT(5)
#define TOTAL_POSITIONS 6
/*
* position_flags identifies which header is requested by the calling func.
* use header_position to find the position of the header associated with
* with the flags.
*/
static void
go_to_next_pos(textsw)
Textsw textsw;
{
Textsw_index pos;
int i = 0;
while (i < TOTAL_POSITIONS && isoff(position_flags, ULBIT(i)))
i++;
if (i == TOTAL_POSITIONS)
return;
if (i < ArraySize(tilde_hdrs))
pos = header_position(textsw, tilde_hdrs[i]);
else
pos = (Textsw_index)window_get(textsw, TEXTSW_LENGTH);
turnoff(position_flags, ULBIT(i));
if (!position_flags)
/* restore old cursor */
window_set(textsw,WIN_CURSOR, window_get(mfprint_sw, WIN_CURSOR), NULL);
else
window_set(textsw, WIN_CURSOR, bentarrow, NULL);
window_set(textsw, TEXTSW_INSERTION_POINT, pos, NULL);
textsw_normalize_view(textsw, (Textsw_index)0);
}
tilde_from_menu(item, value, event)
Panel_item item;
int value;
Event *event;
{
Textsw textsw = (Textsw)panel_get(panel_get(item, PANEL_PARENT_PANEL),
PANEL_CLIENT_DATA);
if (value == 0 || event_id(event) == MS_LEFT)
position_flags = POSITION_ALL;
else
turnon(position_flags, ULBIT(value - 1));
panel_set_value(item, 0);
go_to_next_pos(textsw);
}
/*
* This interpose function is here to parse for tilde escapes.
* Note: this is a (currently) undocumented feature and is intended
* as an accelerator for advanced users. Supported tilde escapes
* are: t,s,c,b,x,e and v.
*/
Notify_value
edit_msg_textwin(textsw, event, arg, type)
Textsw textsw;
Event *event;
Notify_arg arg;
Notify_event_type type;
{
char buf[2];
static char do_tilde;
Textsw_index pos;
if (do_tilde == 1 && event_is_ascii(event) &&
/* make sure we are going to catch this switch */
index("bschetv", event_id(event))) {
textsw_erase(textsw,
(unsigned)window_get(textsw, TEXTSW_INSERTION_POINT)-1,
(unsigned)window_get(textsw, TEXTSW_INSERTION_POINT));
switch (event_id(event)) {
case 'h':
turnon(position_flags, POSITION_ALL);
when 't':
turnon(position_flags, POSITION_TO);
when 's':
turnon(position_flags, POSITION_SUBJ);
when 'c':
turnon(position_flags, POSITION_CC);
when 'b':
turnon(position_flags, POSITION_BCC);
when 'e' : case 'v' : {
/* shouldn't use global -- hack for now */
extern Panel_item edit_item;
do_edit(edit_item);
return NOTIFY_DONE;
}
}
do_tilde = 0;
go_to_next_pos(textsw);
return NOTIFY_DONE;
}
do_tilde = 0;
/* check to see if this is a potential tilde escape */
if (event_id(event) == *escape) {
/* get previous character entered */
pos = (Textsw_index)window_get(textsw, TEXTSW_INSERTION_POINT);
if (pos > 0)
(void) window_get(textsw, TEXTSW_CONTENTS, pos-1, buf, 1);
/* test to see if ~ came at the beginning of a line */
if (pos < 1 || buf[0] == '\n')
do_tilde = 1;
}
/* check for auto-next-header .. e.g. when you hit CR on To: go to Subj:
* special case backspace keys since textsw_start_of_display_line() has
* a bug where it gets the line # wrong when backspacing.
*/
if (position_flags != 0L && ID != CTRL('H') && ID != 127) {
Notify_value val;
if (ID == '\n' || ID == '\r') {
go_to_next_pos(textsw);
return NOTIFY_DONE; /* don't process event */
}
/* we're still processing this header -- continue to do so unless
* the event in question changes the line# of the insertion point.
* first get current position...
*/
pos = (Textsw_index)window_get(textsw, TEXTSW_INSERTION_POINT);
/* now let the event be processed... */
val = notify_next_event_func(textsw, event, arg, type);
/* see if the line # for the new insertion point has changed. */
if (textsw_start_of_display_line(textsw, pos) !=
textsw_start_of_display_line(textsw,
(Textsw_index)window_get(textsw, TEXTSW_INSERTION_POINT))) {
/* the event (mouse button, ACTION_??), changed the line # */
position_flags = 0L; /* disable auto-next-header */
/* restore cursor */
window_set(textsw,
WIN_CURSOR, window_get(mfprint_sw, WIN_CURSOR),
NULL);
}
return val;
}
return notify_next_event_func(textsw, event, arg, type);
}
/*
* start the compose textsw. This is here because we need position_flags
* and the tilde-bits to set the insertion point at the To: line if
* do_position is true.
*/
void
start_textsw_edit(textsw, do_position)
Textsw textsw;
{
extern char *hfile;
char *file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA);
Textsw_index first, last, to_index;
int i;
strdup(file, hfile);
#ifdef SUN_4_0 /* SunOS 4.0+ */
window_set(textsw,
TEXTSW_CLIENT_DATA, file,
TEXTSW_FILE_CONTENTS, hfile,
TEXTSW_READ_ONLY, FALSE,
TEXTSW_STORE_CHANGES_FILE, FALSE,
NULL);
#else /* SUN_4_0 */
textsw_load_file(textsw, hfile, 1, 0, 0);
window_set(textsw,
TEXTSW_CLIENT_DATA, file,
TEXTSW_READ_ONLY, FALSE,
TEXTSW_STORE_CHANGES_FILE, FALSE,
NULL);
#endif /* SUN_4_0 */
position_flags = 0L;
if (do_position) {
turnon(position_flags, POSITION_TO);
if (do_set(set_options, "ask") || do_set(set_options, "asksub"))
turnon(position_flags, POSITION_SUBJ);
if (do_set(set_options, "askcc"))
turnon(position_flags, POSITION_CC);
}
turnon(position_flags, POSITION_END);
go_to_next_pos(textsw);
(void) unlink(hfile);
xfree(hfile), hfile = NULL;
}
/*ARGSUSED*/
void
do_edit(item, value, event)
Panel_item item;
int value;
register Event *event;
{
int argc;
char *file, **argv, *edit, cmd[MAXPATHLEN];
Panel_item next;
Panel panel = (Panel)panel_get(item, PANEL_PARENT_PANEL);
Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA);
file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA);
if (textsw_store_file(textsw, file, 0, 0)) {
error("Can't start editor");
return;
}
if ((!(edit = do_set(set_options, "visual")) || !*edit) &&
(!(edit = do_set(set_options, "editor")) || !*edit))
edit = DEF_EDITOR;
(void) sprintf(cmd, "%s %s", edit, file);
argc = 0;
if (!(argv = mk_argv(cmd, &argc, FALSE))) {
unlink(file);
return;
}
if (tool_edit_letter(textsw, argv) > -1) {
/* skip first panel item */
item = (Panel_item) panel_get(panel, PANEL_FIRST_ITEM);
for (item = (Panel_item) panel_get(item, PANEL_NEXT_ITEM);
item; item = next) {
next = (Panel_item) panel_get(item, PANEL_NEXT_ITEM);
(void) panel_set(item, PANEL_SHOW_ITEM, FALSE, NULL);
}
position_flags = 0L;
window_set(textsw,WIN_CURSOR, window_get(mfprint_sw,WIN_CURSOR), NULL);
}
free_vec(argv);
}