|
|
1.1 root 1: /* Functions for Sun Windows menus and selection buffer.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU Emacs.
5:
6: GNU Emacs is distributed in the hope that it will be useful,
7: but without any warranty. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing.
11:
12: Everyone is granted permission to copy, modify and redistribute
13: GNU Emacs, but only under the conditions described in the
14: document "GNU Emacs copying permission notice". An exact copy
15: of the document is supposed to have been given to you along with
16: GNU Emacs so that you can know how you may redistribute it all.
17: It should be in a file named COPYING. Among other things, the
18: copyright notice and this notice must be preserved on all copies.
19:
20: Author: Jeff Peck, Sun Microsystems, Inc. <[email protected]>
21: Original ideas by David Kastan and Eric Negaard, SRI International
22: Major help from: Steve Greenbaum, Reasoning Systems, Inc.
23: <[email protected]>
24: who first discovered the Menu_Base_Kludge.
25: */
26:
27: /*
28: * Emacs Lisp-Callable functions for sunwindows
29: */
30: #include "config.h"
31:
32: #include <stdio.h>
33: #include <errno.h>
34: #include <signal.h>
35: #include <sunwindow/window_hs.h>
36: #include <suntool/selection.h>
37: #include <suntool/menu.h>
38: #include <suntool/walkmenu.h>
39: #include <suntool/frame.h>
40: #include <suntool/window.h>
41:
42: #include <fcntl.h>
43: #undef NULL /* We don't need sunview's idea of NULL */
44: #include "lisp.h"
45: #include "window.h"
46: #include "buffer.h"
47: #include "termhooks.h"
48:
49: /* conversion to/from character & screen coordinates */
50: /* From Gosling Emacs SunWindow driver by Chris Torek */
51:
52: /* Chars to screen coords. Note that we speak in zero origin. */
53: #define CtoSX(cx) ((cx) * Sun_Font_Xsize)
54: #define CtoSY(cy) ((cy) * Sun_Font_Ysize)
55:
56: /* Screen coords to chars */
57: #define StoCX(sx) ((sx) / Sun_Font_Xsize)
58: #define StoCY(sy) ((sy) / Sun_Font_Ysize)
59:
60: #define CHECK_GFX(x) if((win_fd<0)&&(Fsun_window_init(),(win_fd<0)))return(x)
61: int win_fd = -1;
62: struct pixfont *Sun_Font; /* The font */
63: int Sun_Font_Xsize; /* Width of font */
64: int Sun_Font_Ysize; /* Height of font */
65:
66: #define Menu_Base_Kludge /* until menu_show_using_fd gets fixed */
67: #ifdef Menu_Base_Kludge
68: static Frame Menu_Base_Frame;
69: static int Menu_Base_fd;
70: static Lisp_Object sm_kludge_string;
71: #endif
72: struct cursor CurrentCursor; /* The current cursor */
73:
74: static short CursorData[16]; /* Build cursor here */
75: static mpr_static(CursorMpr, 16, 16, 1, CursorData);
76: static struct cursor NewCursor = {0, 0, PIX_SRC ^ PIX_DST, &CursorMpr};
77:
78: #define RIGHT_ARROW_CURSOR /* if you want the right arrow */
79: #ifdef RIGHT_ARROW_CURSOR
80: /* The default right-arrow cursor, with XOR drawing. */
81: static short ArrowCursorData[16] = {
82: 0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,0x000F,
83: 0x001B,0x0019,0x0030,0x0030,0x0060,0x0060,0x00C0,0x00C0};
84: static mpr_static(ArrowCursorMpr, 16, 16, 1, ArrowCursorData);
85: struct cursor DefaultCursor = {15, 0, PIX_SRC ^ PIX_DST, &ArrowCursorMpr};
86:
87: #else
88: /* The default left-arror cursor, with XOR drawing. */
89: static short ArrowCursorData[16] = {
90: 0x8000,0xC000,0xE000,0xF000,0xF800,0xFC00,0xFE00,0xF000,
91: 0xD800,0x9800,0x0C00,0x0C00,0x0600,0x0600,0x0300,0x0300};
92: static mpr_static(ArrowCursorMpr, 16, 16, 1, ArrowCursorData);
93: struct cursor DefaultCursor = {0, 0, PIX_SRC ^ PIX_DST, &ArrowCursorMpr};
94: #endif
95:
96: /*
97: * Initialize window
98: */
99: DEFUN ("sun-window-init", Fsun_window_init, Ssun_window_init, 0, 1, 0,
100: "One time setup for using Sun Windows with mouse.\n\
101: Unless optional argument FORCE is non-nil, is a noop after its first call.\n\
102: Returns a number representing the file descriptor of the open Sun Window,\n\
103: or -1 if can not open it.")
104: (force)
105: Lisp_Object force;
106: {
107: char *cp;
108: static int already_initialized = 0;
109:
110: if ((! already_initialized) || (!NULL(force))) {
111: cp = getenv("WINDOW_GFX");
112: if (cp != 0) win_fd = open(cp, 2);
113: if (win_fd > 0)
114: {
115: Sun_Font = pf_default();
116: Sun_Font_Xsize = Sun_Font->pf_defaultsize.x;
117: Sun_Font_Ysize = Sun_Font->pf_defaultsize.y;
118: Fsun_change_cursor_icon (Qnil); /* set up the default cursor */
119: already_initialized = 1;
120: #ifdef Menu_Base_Kludge
121:
122: /* Make a frame to use for putting the menu on, and get its fd. */
123: Menu_Base_Frame = window_create(0, FRAME,
124: WIN_X, 0, WIN_Y, 0,
125: WIN_ROWS, 1, WIN_COLUMNS, 1,
126: WIN_SHOW, FALSE,
127: FRAME_NO_CONFIRM, 1,
128: 0);
129: Menu_Base_fd = (int) window_get(Menu_Base_Frame, WIN_FD);
130: #endif
131: }
132: }
133: return(make_number(win_fd));
134: }
135:
136: /*
137: * Mouse sit-for (allows a shorter interval than the regular sit-for
138: * and can be interrupted by the mouse)
139: */
140: DEFUN ("sit-for-millisecs", Fsit_for_millisecs, Ssit_for_millisecs, 1, 1, 0,
141: "Like sit-for, but ARG is milliseconds. \n\
142: Perform redisplay, then wait for ARG milliseconds or until\n\
143: input is available. Returns t if wait completed with no input.\n\
144: Redisplay does not happen if input is available before it starts.")
145: (n)
146: Lisp_Object n;
147: {
148: struct timeval Timeout;
149: int waitmask = 1;
150:
151: CHECK_NUMBER (n, 0);
152: Timeout.tv_sec = XINT(n) / 1000;
153: Timeout.tv_usec = (XINT(n) - (Timeout.tv_sec * 1000)) * 1000;
154:
155: if (detect_input_pending()) return(Qnil);
156: DoDsp(1);
157: /*
158: * Check for queued keyboard input/mouse hits again
159: * (A bit screen update can take some time!)
160: */
161: if (detect_input_pending()) return(Qnil);
162: select(1,&waitmask,0,0,&Timeout);
163: if (detect_input_pending()) return(Qnil);
164: return(Qt);
165: }
166:
167: /*
168: * Sun sleep-for (allows a shorter interval than the regular sleep-for)
169: */
170: DEFUN ("sleep-for-millisecs",
171: Fsleep_for_millisecs,
172: Ssleep_for_millisecs, 1, 1, 0,
173: "Pause, without updating display, for ARG milliseconds.")
174: (n)
175: Lisp_Object n;
176: {
177: unsigned useconds;
178:
179: CHECK_NUMBER (n, 0);
180: useconds = XINT(n) * 1000;
181: usleep(useconds);
182: return(Qt);
183: }
184:
185: DEFUN ("update-display", Fupdate_display, Supdate_display, 0, 0, 0,
186: "Perform redisplay.")
187: ()
188: {
189: DoDsp(1);
190: return(Qt);
191: }
192:
193:
194: /*
195: * Change the Sun mouse icon
196: */
197: DEFUN ("sun-change-cursor-icon",
198: Fsun_change_cursor_icon,
199: Ssun_change_cursor_icon, 1, 1, 0,
200: "Change the Sun mouse cursor icon. ICON is a lisp vector whose 1st element\n\
201: is the X offset of the cursor hot-point, whose 2nd element is the Y offset\n\
202: of the cursor hot-point and whose 3rd element is the cursor pixel data\n\
203: expressed as a string. If ICON is nil then the original arrow cursor is used")
204: (Icon)
205: Lisp_Object Icon;
206: {
207: register unsigned char *cp;
208: register short *p;
209: register int i;
210: Lisp_Object X_Hot, Y_Hot, Data;
211:
212: CHECK_GFX (Qnil);
213: /*
214: * If the icon is null, we just restore the DefaultCursor
215: */
216: if (NULL(Icon))
217: CurrentCursor = DefaultCursor;
218: else {
219: /*
220: * extract the data from the vector
221: */
222: CHECK_VECTOR (Icon, 0);
223: if (XVECTOR(Icon)->size < 3) return(Qnil);
224: X_Hot = XVECTOR(Icon)->contents[0];
225: Y_Hot = XVECTOR(Icon)->contents[1];
226: Data = XVECTOR(Icon)->contents[2];
227:
228: CHECK_NUMBER (X_Hot, 0);
229: CHECK_NUMBER (Y_Hot, 0);
230: CHECK_STRING (Data, 0);
231: if (XSTRING(Data)->size != 32) return(Qnil);
232: /*
233: * Setup the new cursor
234: */
235: NewCursor.cur_xhot = X_Hot;
236: NewCursor.cur_yhot = Y_Hot;
237: cp = XSTRING(Data)->data;
238: p = CursorData;
239: i = 16;
240: while(--i >= 0)
241: *p++ = (cp[0] << 8) | cp[1], cp += 2;
242: CurrentCursor = NewCursor;
243: }
244: win_setcursor(win_fd, &CurrentCursor);
245: return(Qt);
246: }
247:
248: /*
249: * Interface for sunwindows selection
250: */
251: static Lisp_Object Current_Selection;
252:
253: static
254: sel_write (sel, file)
255: struct selection *sel;
256: FILE *file;
257: {
258: fwrite (XSTRING (Current_Selection)->data, sizeof (char),
259: sel->sel_items, file);
260: }
261:
262: static
263: sel_clear (sel, windowfd)
264: struct selection *sel;
265: int windowfd;
266: {
267: }
268:
269: static
270: sel_read (sel, file)
271: struct selection *sel;
272: FILE *file;
273: {
274: register int i, n;
275: register char *cp;
276:
277: Current_Selection = make_string ("", 0);
278: if (sel->sel_items <= 0)
279: return (0);
280: cp = (char *) malloc(sel->sel_items);
281: if (cp == (char *)0) {
282: error("malloc failed in sel_read");
283: return(-1);
284: }
285: n = fread(cp, sizeof(char), sel->sel_items, file);
286: if (n > sel->sel_items) {
287: error("fread botch in sel_read");
288: return(-1);
289: } else if (n < 0) {
290: error("Error reading selection.");
291: return(-1);
292: }
293: /*
294: * The shelltool select saves newlines as carrige returns,
295: * but emacs wants newlines.
296: */
297: for (i = 0; i < n; i++)
298: if (cp[i] == '\r') cp[i] = '\n';
299:
300: Current_Selection = make_string (cp, n);
301: free (cp);
302: return (0);
303: }
304:
305: /*
306: * Set the window system "selection" to be the arg STRING
307: */
308: DEFUN ("sun-set-selection", Fsun_set_selection, Ssun_set_selection, 1, 1,
309: "sSet selection to: ",
310: "Set the current sunwindow selection to STRING.")
311: (str)
312: Lisp_Object str;
313: {
314: struct selection selection;
315:
316: CHECK_STRING (str, 0);
317: Current_Selection = str;
318:
319: CHECK_GFX (Qnil);
320: selection.sel_type = SELTYPE_CHAR;
321: selection.sel_items = XSTRING (str)->size;
322: selection.sel_itembytes = 1;
323: selection.sel_pubflags = 1;
324: selection_set(&selection, sel_write, sel_clear, win_fd);
325: return (Qt);
326: }
327: /*
328: * Stuff the current window system selection into the current buffer
329: */
330: DEFUN ("sun-get-selection", Fsun_get_selection, Ssun_get_selection, 0, 0, 0,
331: "Return the current sunwindows selection as a string.")
332: ()
333: {
334: CHECK_GFX (Current_Selection);
335: selection_get (sel_read, win_fd);
336: return (Current_Selection);
337: }
338:
339: Menu sun_menu_create();
340:
341: Menu_item
342: sun_item_create (Pair)
343: Lisp_Object Pair;
344: {
345: /* In here, we depend on Lisp supplying zero terminated strings in the data*/
346: /* so we can just pass the pointers, and not recopy anything */
347:
348: Menu_item menu_item;
349: Menu submenu;
350: Lisp_Object String;
351: Lisp_Object Value;
352:
353: if (!CONSP(Pair)) wrong_type_argument(Qlistp, Pair);
354: String = Fcar(Pair);
355: CHECK_STRING(String, 0);
356: Value = Fcdr(Pair);
357: if(XTYPE(Value) == Lisp_Symbol)
358: Value = XSYMBOL(Value)->value;
359: if(XTYPE(Value) == Lisp_Vector) {
360: submenu = sun_menu_create (Value);
361: menu_item = menu_create_item
362: (MENU_RELEASE, MENU_PULLRIGHT_ITEM, XSTRING(String)->data, submenu, 0);
363: } else {
364: menu_item = menu_create_item
365: (MENU_RELEASE, MENU_STRING_ITEM, XSTRING(String)->data, Value, 0);
366: }
367: return menu_item;
368: }
369:
370: Menu
371: sun_menu_create (Vector)
372: Lisp_Object Vector;
373: {
374: Menu menu;
375: int i;
376: CHECK_VECTOR(Vector,0);
377: menu=menu_create(0);
378: for(i = 0; i < XVECTOR(Vector)->size; i++) {
379: menu_set (menu, MENU_APPEND_ITEM,
380: sun_item_create(XVECTOR(Vector)->contents[i]), 0);
381: }
382: return menu;
383: }
384:
385: /*
386: * If the first item of the menu has nil as its value, then make the
387: * item look like a label by inverting it and making it unselectable.
388: * Returns 1 if the label was made, 0 otherwise.
389: */
390: int
391: make_menu_label (menu)
392: Menu menu;
393: {
394: int made_label_p = 0;
395:
396: if (( menu_get(menu, MENU_NITEMS) > 0 ) && /* At least one item */
397: ((Lisp_Object) menu_get(menu_get(menu, MENU_NTH_ITEM, 1),
398: MENU_VALUE) == Qnil )) {
399: menu_set(menu_get(menu, MENU_NTH_ITEM, 1),
400: MENU_INVERT, TRUE,
401: MENU_FEEDBACK, FALSE,
402: 0);
403: made_label_p = 1;
404: }
405: return made_label_p;
406: }
407:
408: /*
409: * Do a pop-up menu and return the selected value
410: */
411: DEFUN ("sun-menu-internal",
412: Fsun_menu_internal,
413: Ssun_menu_internal, 5, 5, 0,
414: "Set up a SunView pop-up menu and return the user's choice.\n\
415: Arguments WINDOW, X, Y, BUTTON, and MENU.\n\
416: *** User code should generally use sun-menu-evaluate ***\n\
417: \n\
418: Arguments WINDOW, X, Y, BUTTON, and MENU.\n\
419: Put MENU up in WINDOW at position X, Y.\n\
420: The BUTTON argument specifies the button to be released that selects an item:\n\
421: 1 = LEFT BUTTON\n\
422: 2 = MIDDLE BUTTON\n\
423: 4 = RIGHT BUTTON\n\
424: The MENU argument is a vector containing (STRING . VALUE) pairs.\n\
425: The VALUE of the selected item is returned.\n\
426: If the VALUE of the first pair is nil, then the first STRING will be used\n\
427: as a menu label.")
428: (window, X_Position, Y_Position, Button, MEnu)
429: Lisp_Object window, X_Position, Y_Position, Button, MEnu;
430: {
431: Menu menu;
432: int button, xpos, ypos;
433: Event event0;
434: Event *event = &event0;
435: Lisp_Object Value, Pair;
436:
437: CHECK_NUMBER(X_Position, 0);
438: CHECK_NUMBER(Y_Position, 1);
439: CHECK_WINDOW(window, 2);
440: CHECK_NUMBER(Button, 3);
441: CHECK_VECTOR(MEnu, 4);
442:
443: CHECK_GFX (Qnil);
444:
445: xpos = CtoSX (XWINDOW(window)->left + XINT(X_Position));
446: ypos = CtoSY (XWINDOW(window)->top + XINT(Y_Position));
447: #ifdef Menu_Base_Kludge
448: {static Lisp_Object symbol[2];
449: symbol[0] = Fintern (sm_kludge_string, Qnil);
450: Pair = Ffuncall (1, symbol);
451: xpos += XINT (XCONS (Pair)->cdr);
452: ypos += XINT (XCONS (Pair)->car);
453: }
454: #endif
455:
456: button = XINT(Button);
457: if(button == 4) button = 3;
458: event_set_id (event, BUT(button));
459: event_set_down (event);
460: event_set_x (event, xpos);
461: event_set_y (event, ypos);
462:
463: menu = sun_menu_create(MEnu);
464: make_menu_label(menu);
465:
466: #ifdef Menu_Base_Kludge
467: Value = (Lisp_Object) menu_show(menu, Menu_Base_Frame, event, 0);
468: #else
469: /* This confuses the notifier or something: */
470: Value = (Lisp_Object) menu_show_using_fd(menu, win_fd, event, 0);
471: /*
472: * Right button gets lost, and event sequencing or delivery gets mixed up
473: * So, until that gets fixed, we use this <Menu_Base_Frame> kludge:
474: */
475: #endif
476: menu_destroy (menu);
477:
478: return ((int)Value ? Value : Qnil);
479: }
480:
481:
482: /*
483: * Define everything
484: */
485: syms_of_sunfns()
486: {
487: #ifdef Menu_Base_Kludge
488: /* i'm just too lazy to re-write this into C code */
489: /* so we will call this elisp function from C */
490: sm_kludge_string = make_pure_string ("sm::menu-kludge", 15);
491: #endif /* Menu_Base_Kludge */
492:
493: defsubr(&Ssun_window_init);
494: defsubr(&Ssit_for_millisecs);
495: defsubr(&Ssleep_for_millisecs);
496: defsubr(&Supdate_display);
497: defsubr(&Ssun_change_cursor_icon);
498: defsubr(&Ssun_set_selection);
499: defsubr(&Ssun_get_selection);
500: defsubr(&Ssun_menu_internal);
501: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.