|
|
1.1 ! root 1: /* ! 2: * ! 3: * Copyright (C) 1986 Free Software Foundation, Inc. ! 4: * ! 5: * This file is part of GNU Emacs. ! 6: * ! 7: * GNU Emacs is distributed in the hope that it will be useful, ! 8: * but without any warranty. No author or distributor ! 9: * accepts responsibility to anyone for the consequences of using it ! 10: * or for whether it serves any particular purpose or works at all, ! 11: * unless he says so in writing. ! 12: * ! 13: * Everyone is granted permission to copy, modify and redistribute ! 14: * GNU Emacs, but only under the conditions described in the ! 15: * document "GNU Emacs copying permission notice". An exact copy ! 16: * of the document is supposed to have been given to you along with ! 17: * GNU Emacs so that you can know how you may redistribute it all. ! 18: * It should be in a file named COPYING. Among other things, the ! 19: * copyright notice and this notice must be preserved on all copies. ! 20: * ! 21: * ! 22: * For Emacs in SunView/Sun-Windows: (supported by Sun Unix v3.2) ! 23: * Insert a notifier filter-function to convert all useful input ! 24: * to "key" sequences that emacs can understand. See: Emacstool(1). ! 25: * ! 26: * Author: Jeff Peck, Sun Microsystems, Inc. <[email protected]> ! 27: * ! 28: * Original Idea: Ian Batten ! 29: * Updated 15-Mar-88, Jeff Peck: set IN_EMACSTOOL, TERM, TERMCAP ! 30: * ! 31: */ ! 32: ! 33: #include <suntool/sunview.h> ! 34: #include <suntool/tty.h> ! 35: #include <stdio.h> ! 36: #include <sys/file.h> ! 37: ! 38: #define BUFFER_SIZE 128 /* Size of all the buffers */ ! 39: ! 40: /* define WANT_CAPS_LOCK to make f-key T1 (aka F1) behave as CapsLock */ ! 41: #define WANT_CAPS_LOCK ! 42: #ifdef WANT_CAPS_LOCK ! 43: int caps_lock; /* toggle indicater for f-key T1 caps lock */ ! 44: static char *Caps = "[CAPS] "; /* Caps Lock prefix string */ ! 45: #define CAPS_LEN 7 /* strlen (Caps) */ ! 46: #endif ! 47: ! 48: static char *mouse_prefix = "\030\000"; /* C-x C-@ */ ! 49: static int m_prefix_length = 2; /* mouse_prefix length */ ! 50: ! 51: static char *key_prefix = "\030*"; /* C-x * */ ! 52: static int k_prefix_length = 2; /* key_prefix length */ ! 53: ! 54: static char *emacs_name = "emacs"; /* default run command */ ! 55: static char buffer[BUFFER_SIZE]; /* send to ttysw_input */ ! 56: static char *title = "Emacstool - "; /* initial title */ ! 57: ! 58: Frame frame; /* Base frame for system */ ! 59: Tty ttysw; /* Where emacs is */ ! 60: int font_width, font_height; /* For translating pixels to chars */ ! 61: ! 62: int console_fd = 0; /* for debugging: setenv DEBUGEMACSTOOL */ ! 63: FILE *console; /* for debugging: setenv DEBUGEMACSTOOL */ ! 64: ! 65: Icon frame_icon; ! 66: /* make an icon_image for the default frame_icon */ ! 67: static short default_image[258] = ! 68: { ! 69: #include <images/terminal.icon> ! 70: }; ! 71: mpr_static(icon_image, 64, 64, 1, default_image); ! 72: ! 73: ! 74: /* ! 75: * Assign a value to a set of keys ! 76: */ ! 77: int ! 78: button_value (event) ! 79: Event *event; ! 80: { ! 81: int retval = 0; ! 82: /* ! 83: * Code up the current situation: ! 84: * ! 85: * 1 = MS_LEFT; ! 86: * 2 = MS_MIDDLE; ! 87: * 4 = MS_RIGHT; ! 88: * 8 = SHIFT; ! 89: * 16 = CONTROL; ! 90: * 32 = META; ! 91: * 64 = DOUBLE; ! 92: * 128 = UP; ! 93: */ ! 94: ! 95: if (MS_LEFT == (event_id (event))) retval = 1; ! 96: if (MS_MIDDLE == (event_id (event))) retval = 2; ! 97: if (MS_RIGHT == (event_id (event))) retval = 4; ! 98: ! 99: if (event_shift_is_down (event)) retval += 8; ! 100: if (event_ctrl_is_down (event)) retval += 16; ! 101: if (event_meta_is_down (event)) retval += 32; ! 102: if (event_is_up (event)) retval += 128; ! 103: return retval; ! 104: } ! 105: ! 106: /* ! 107: * Variables to store the time of the previous mouse event that was ! 108: * sent to emacs. ! 109: * ! 110: * The theory is that to time double clicks while ignoreing UP buttons, ! 111: * we must keep track of the accumulated time. ! 112: * ! 113: * If someone writes a SUN-SET-INPUT-MASK for emacstool, ! 114: * That could be used to selectively disable UP events, ! 115: * and then this cruft wouldn't be necessary. ! 116: */ ! 117: static long prev_event_sec = 0; ! 118: static long prev_event_usec = 0; ! 119: ! 120: /* ! 121: * Give the time difference in milliseconds, where one second ! 122: * is considered infinite. ! 123: */ ! 124: int ! 125: time_delta (now_sec, now_usec, prev_sec, prev_usec) ! 126: long now_sec, now_usec, prev_sec, prev_usec; ! 127: { ! 128: long sec_delta = now_sec - prev_sec; ! 129: long usec_delta = now_usec - prev_usec; ! 130: ! 131: if (usec_delta < 0) { /* "borrow" a second */ ! 132: usec_delta += 1000000; ! 133: --sec_delta; ! 134: } ! 135: ! 136: if (sec_delta >= 10) ! 137: return (9999); /* Infinity */ ! 138: else ! 139: return ((sec_delta * 1000) + (usec_delta / 1000)); ! 140: } ! 141: ! 142: ! 143: /* ! 144: * Filter function to translate selected input events for emacs ! 145: * Mouse button events become ^X^@(button x-col y-line time-delta) . ! 146: * Function keys: ESC-*{c}{lrt} l,r,t for Left, Right, Top; ! 147: * {c} encodes the keynumber as a character [a-o] ! 148: */ ! 149: static Notify_value ! 150: input_event_filter_function (window, event, arg, type) ! 151: Window window; ! 152: Event *event; ! 153: Notify_arg arg; ! 154: Notify_event_type type; ! 155: { ! 156: struct timeval time_stamp; ! 157: ! 158: if (console_fd) fprintf(console, "Event: %d\n", event_id(event)); ! 159: ! 160: /* UP L1 is the STOP key */ ! 161: if (event_id(event) == WIN_STOP) { ! 162: ttysw_input(ttysw, "\007\007\007\007\007\007\007", 7); ! 163: return NOTIFY_IGNORED; ! 164: } ! 165: ! 166: /* UP L5 & L7 is Expose & Open, let them pass to sunview */ ! 167: if (event_id(event) == KEY_LEFT(5) || event_id(event) == KEY_LEFT(7)) ! 168: if(event_is_up (event)) ! 169: return notify_next_event_func (window, event, arg, type); ! 170: else return NOTIFY_IGNORED; ! 171: ! 172: if (event_is_button (event)) { /* do Mouse Button events */ ! 173: /* Commented out so that we send mouse up events too. ! 174: if (event_is_up (event)) ! 175: return notify_next_event_func (window, event, arg, type); ! 176: */ ! 177: time_stamp = event_time (event); ! 178: ttysw_input (ttysw, mouse_prefix, m_prefix_length); ! 179: sprintf (buffer, "(%d %d %d %d)\015", ! 180: button_value (event), ! 181: event_x (event) / font_width, ! 182: event_y (event) / font_height, ! 183: time_delta (time_stamp.tv_sec, time_stamp.tv_usec, ! 184: prev_event_sec, prev_event_usec) ! 185: ); ! 186: ttysw_input (ttysw, buffer, strlen(buffer)); ! 187: prev_event_sec = time_stamp.tv_sec; ! 188: prev_event_usec = time_stamp.tv_usec; ! 189: return NOTIFY_IGNORED; ! 190: } ! 191: ! 192: { /* Do the function key events */ ! 193: int d; ! 194: char c = (char) 0; ! 195: if ((event_is_key_left (event)) ? ! 196: ((d = event_id(event) - KEY_LEFT(1) + 'a'), c='l') : ! 197: ((event_is_key_right (event)) ? ! 198: ((d = event_id(event) - KEY_RIGHT(1) + 'a'), c='r') : ! 199: ((event_is_key_top (event)) ? ! 200: ((d = event_id(event) - KEY_TOP(1) + 'a'), c='t') : 0))) ! 201: { ! 202: if (event_is_up(event)) return NOTIFY_IGNORED; ! 203: if (event_shift_is_down (event)) c = c - 32; ! 204: /* this will give a non-{lrt} for unshifted keys */ ! 205: if (event_ctrl_is_down (event)) c = c - 64; ! 206: if (event_meta_is_down (event)) c = c + 128; ! 207: #ifdef WANT_CAPS_LOCK ! 208: /* set a toggle and relabel window so T1 can act like caps-lock */ ! 209: if (event_id(event) == KEY_TOP(1)) ! 210: { ! 211: /* make a frame label with and without CAPS */ ! 212: strcpy (buffer, Caps); ! 213: title = &buffer[CAPS_LEN]; ! 214: strncpy (title, (char *)window_get (frame, FRAME_LABEL), ! 215: BUFFER_SIZE - CAPS_LEN); ! 216: buffer[BUFFER_SIZE] = (char) 0; ! 217: if (strncmp (title, Caps, CAPS_LEN) == 0) ! 218: title += CAPS_LEN; /* already Caps */ ! 219: caps_lock = (caps_lock ? 0 : CAPS_LEN); ! 220: window_set(frame, FRAME_LABEL, (title -= caps_lock), 0); ! 221: return NOTIFY_IGNORED; ! 222: } ! 223: #endif ! 224: ttysw_input (ttysw, key_prefix, k_prefix_length); ! 225: sprintf (buffer, "%c%c", d, c); ! 226: ttysw_input(ttysw, buffer, strlen(buffer)); ! 227: ! 228: return NOTIFY_IGNORED; ! 229: } ! 230: } ! 231: if ((event_is_ascii(event) || event_is_meta(event)) ! 232: && event_is_up(event)) return NOTIFY_IGNORED; ! 233: #ifdef WANT_CAPS_LOCK ! 234: /* shift alpha chars to upper case if toggle is set */ ! 235: if ((caps_lock) && event_is_ascii(event) ! 236: && (event_id(event) >= 'a') && (event_id(event) <= 'z')) ! 237: event_set_id(event, (event_id(event) - 32)); ! 238: /* crufty, but it works for now. is there an UPCASE(event)? */ ! 239: #endif ! 240: return notify_next_event_func (window, event, arg, type); ! 241: } ! 242: ! 243: main (argc, argv) ! 244: int argc; ! 245: char **argv; ! 246: { ! 247: int error_code; /* Error codes */ ! 248: ! 249: if(getenv("DEBUGEMACSTOOL")) ! 250: console = fdopen (console_fd = open("/dev/console",O_WRONLY), "w"); ! 251: ! 252: /* do this first, so arglist can override it */ ! 253: frame_icon = icon_create (ICON_LABEL, "Emacstool", ! 254: ICON_IMAGE, &icon_image, ! 255: 0); ! 256: ! 257: putenv("IN_EMACSTOOL=t"); /* notify subprocess that it is in emacstool */ ! 258: ! 259: if (putenv("TERM=sun") != 0) /* TTYSW will be a TERM=sun window */ ! 260: {fprintf (stderr, "%s: Could not set TERM=sun, using `%s'\n", ! 261: argv[0], (char *)getenv("TERM")) ;}; ! 262: /* ! 263: * If TERMCAP starts with a slash, it is the pathname of the ! 264: * termcap file, not an entry extracted from it, so KEEP it! ! 265: * Otherwise, it may not relate to the new TERM, so Nuke-It. ! 266: * If there is no TERMCAP environment variable, don't make one. ! 267: */ ! 268: { ! 269: char *termcap ; /* Current TERMCAP value */ ! 270: termcap = (char *)getenv("TERMCAP") ; ! 271: if (termcap && (*termcap != '/')) ! 272: { ! 273: if (putenv("TERMCAP=") != 0) ! 274: {fprintf (stderr, "%s: Could not clear TERMCAP\n", argv[0]) ;} ; ! 275: } ; ! 276: } ; ! 277: ! 278: /* find command to run as subprocess in window */ ! 279: if (!(argv[0] = (char *)getenv("EMACSTOOL"))) /* Set emacs command name */ ! 280: argv[0] = emacs_name; ! 281: for (argc = 1; argv[argc]; argc++) /* Use last one on line */ ! 282: if(!(strcmp ("-rc", argv[argc]))) /* Override if -rc given */ ! 283: { ! 284: int i = argc; ! 285: argv[argc--]=0; /* kill the -rc argument */ ! 286: if (argv[i+1]) { /* move to agrv[0] and squeeze the rest */ ! 287: argv[0]=argv[i+1]; ! 288: for (; argv[i+2]; (argv[i]=argv[i+2],argv[++i]=0)); ! 289: } ! 290: } ! 291: ! 292: strcpy (buffer, title); ! 293: strncat (buffer, argv[0], /* append run command name */ ! 294: (BUFFER_SIZE - (strlen (buffer)) - (strlen (argv[0]))) - 1); ! 295: ! 296: /* Build a frame to run in */ ! 297: frame = window_create ((Window)NULL, FRAME, ! 298: FRAME_LABEL, buffer, ! 299: FRAME_ICON, frame_icon, ! 300: FRAME_ARGC_PTR_ARGV, &argc, argv, ! 301: 0); ! 302: ! 303: /* Create a tty with emacs in it */ ! 304: ttysw = window_create (frame, TTY, ! 305: TTY_QUIT_ON_CHILD_DEATH, TRUE, ! 306: TTY_BOLDSTYLE, 8, ! 307: TTY_ARGV, argv, ! 308: 0); ! 309: ! 310: window_set(ttysw, ! 311: WIN_CONSUME_PICK_EVENTS, ! 312: WIN_STOP, ! 313: WIN_MOUSE_BUTTONS, WIN_UP_EVENTS, ! 314: /* LOC_WINENTER, LOC_WINEXIT, LOC_MOVE, */ ! 315: 0, ! 316: ! 317: WIN_CONSUME_KBD_EVENTS, ! 318: WIN_STOP, ! 319: WIN_ASCII_EVENTS, ! 320: WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, ! 321: /* WIN_UP_ASCII_EVENTS, */ ! 322: 0, ! 323: ! 324: 0); ! 325: ! 326: font_height = (int)window_get (ttysw, WIN_ROW_HEIGHT); ! 327: font_width = (int)window_get (ttysw, WIN_COLUMN_WIDTH); ! 328: ! 329: /* Interpose my event function */ ! 330: error_code = (int) notify_interpose_event_func ! 331: (ttysw, input_event_filter_function, NOTIFY_SAFE); ! 332: ! 333: if (error_code != 0) /* Barf */ ! 334: { ! 335: fprintf (stderr, "notify_interpose_event_func got %d.\n", error_code); ! 336: exit (1); ! 337: } ! 338: ! 339: window_main_loop (frame); /* And away we go */ ! 340: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.