diff options
| author | Joseph Arceneaux | 1989-10-31 16:00:07 +0000 |
|---|---|---|
| committer | Joseph Arceneaux | 1989-10-31 16:00:07 +0000 |
| commit | a2535589a9b419920395f37ef658a3c88bf13ecb (patch) | |
| tree | 0ad1d0f49cfeefe0012f44708b76adcd902806eb /lib-src | |
| parent | 0d20f9a04efa7cfbe205e4967b6797b89fc64fe7 (diff) | |
| download | emacs-a2535589a9b419920395f37ef658a3c88bf13ecb.tar.gz emacs-a2535589a9b419920395f37ef658a3c88bf13ecb.zip | |
Initial revision
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/emacstool.c | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/lib-src/emacstool.c b/lib-src/emacstool.c new file mode 100644 index 00000000000..5e310e0faa4 --- /dev/null +++ b/lib-src/emacstool.c | |||
| @@ -0,0 +1,340 @@ | |||
| 1 | /* | ||
| 2 | * | ||
| 3 | * Copyright (C) 1986 Free Software Foundation, Inc. | ||
| 4 | * | ||
| 5 | * This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 1, or (at your option) | ||
| 10 | any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 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. <peck@sun.com> | ||
| 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 | } | ||