home *** CD-ROM | disk | FTP | other *** search
- /* @(#)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);
- }
-