1 /* Functions for Sun Windows menus and selection buffer.
2 Copyright (C) 1987 Free Software Foundation, Inc.
4 This file is probably totally obsolete. In any case, the FSF is
5 unwilling to support it. We agreed to include it in our distribution
6 only on the understanding that we would spend no time at all on it.
8 If you have complaints about this file, send them to peck@sun.com.
9 If no one at Sun wants to maintain this, then consider it not
10 maintained at all. It would be a bad thing for the GNU project if
11 this file took our effort away from higher-priority things.
14 This file is part of GNU Emacs.
16 GNU Emacs is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 1, or (at your option)
21 GNU Emacs is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with GNU Emacs; see the file COPYING. If not, write to
28 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
30 /* Author: Jeff Peck, Sun Microsystems, Inc. <peck@sun.com>
31 Original ideas by David Kastan and Eric Negaard, SRI International
32 Major help from: Steve Greenbaum, Reasoning Systems, Inc.
34 who first discovered the Menu_Base_Kludge.
38 * Emacs Lisp-Callable functions for sunwindows
45 #include <sunwindow/window_hs.h>
46 #include <suntool/selection.h>
47 #include <suntool/menu.h>
48 #include <suntool/walkmenu.h>
49 #include <suntool/frame.h>
50 #include <suntool/window.h>
53 #undef NULL /* We don't need sunview's idea of NULL */
57 #include "termhooks.h"
59 /* conversion to/from character & frame coordinates */
60 /* From Gosling Emacs SunWindow driver by Chris Torek */
62 /* Chars to frame coords. Note that we speak in zero origin. */
63 #define CtoSX(cx) ((cx) * Sun_Font_Xsize)
64 #define CtoSY(cy) ((cy) * Sun_Font_Ysize)
66 /* Frame coords to chars */
67 #define StoCX(sx) ((sx) / Sun_Font_Xsize)
68 #define StoCY(sy) ((sy) / Sun_Font_Ysize)
70 #define CHECK_GFX(x) if((win_fd<0)&&(Fsun_window_init(),(win_fd<0)))return(x)
72 struct pixfont
*Sun_Font
; /* The font */
73 int Sun_Font_Xsize
; /* Width of font */
74 int Sun_Font_Ysize
; /* Height of font */
76 #define Menu_Base_Kludge /* until menu_show_using_fd gets fixed */
77 #ifdef Menu_Base_Kludge
78 static Frame Menu_Base_Frame
;
79 static int Menu_Base_fd
;
80 static Lisp_Object sm_kludge_string
;
82 struct cursor CurrentCursor
; /* The current cursor */
84 static short CursorData
[16]; /* Build cursor here */
85 static mpr_static(CursorMpr
, 16, 16, 1, CursorData
);
86 static struct cursor NewCursor
= {0, 0, PIX_SRC
^ PIX_DST
, &CursorMpr
};
88 #define RIGHT_ARROW_CURSOR /* if you want the right arrow */
89 #ifdef RIGHT_ARROW_CURSOR
90 /* The default right-arrow cursor, with XOR drawing. */
91 static short ArrowCursorData
[16] = {
92 0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,0x000F,
93 0x001B,0x0019,0x0030,0x0030,0x0060,0x0060,0x00C0,0x00C0};
94 static mpr_static(ArrowCursorMpr
, 16, 16, 1, ArrowCursorData
);
95 struct cursor DefaultCursor
= {15, 0, PIX_SRC
^ PIX_DST
, &ArrowCursorMpr
};
98 /* The default left-arrow cursor, with XOR drawing. */
99 static short ArrowCursorData
[16] = {
100 0x8000,0xC000,0xE000,0xF000,0xF800,0xFC00,0xFE00,0xF000,
101 0xD800,0x9800,0x0C00,0x0C00,0x0600,0x0600,0x0300,0x0300};
102 static mpr_static(ArrowCursorMpr
, 16, 16, 1, ArrowCursorData
);
103 struct cursor DefaultCursor
= {0, 0, PIX_SRC
^ PIX_DST
, &ArrowCursorMpr
};
109 DEFUN ("sun-window-init", Fsun_window_init
, Ssun_window_init
, 0, 1, 0,
110 "One time setup for using Sun Windows with mouse.\n\
111 Unless optional argument FORCE is non-nil, is a noop after its first call.\n\
112 Returns a number representing the file descriptor of the open Sun Window,\n\
113 or -1 if can not open it.")
118 static int already_initialized
= 0;
120 if ((! already_initialized
) || (!NILP(force
))) {
121 cp
= getenv("WINDOW_GFX");
122 if (cp
!= 0) win_fd
= open(cp
, 2);
125 Sun_Font
= pf_default();
126 Sun_Font_Xsize
= Sun_Font
->pf_defaultsize
.x
;
127 Sun_Font_Ysize
= Sun_Font
->pf_defaultsize
.y
;
128 Fsun_change_cursor_icon (Qnil
); /* set up the default cursor */
129 already_initialized
= 1;
130 #ifdef Menu_Base_Kludge
132 /* Make a frame to use for putting the menu on, and get its fd. */
133 Menu_Base_Frame
= window_create(0, FRAME
,
135 WIN_ROWS
, 1, WIN_COLUMNS
, 1,
139 Menu_Base_fd
= (int) window_get(Menu_Base_Frame
, WIN_FD
);
143 return(make_number(win_fd
));
147 * Mouse sit-for (allows a shorter interval than the regular sit-for
148 * and can be interrupted by the mouse)
150 DEFUN ("sit-for-millisecs", Fsit_for_millisecs
, Ssit_for_millisecs
, 1, 1, 0,
151 "Like sit-for, but ARG is milliseconds. \n\
152 Perform redisplay, then wait for ARG milliseconds or until\n\
153 input is available. Returns t if wait completed with no input.\n\
154 Redisplay does not happen if input is available before it starts.")
158 struct timeval Timeout
;
162 Timeout
.tv_sec
= XINT(n
) / 1000;
163 Timeout
.tv_usec
= (XINT(n
) - (Timeout
.tv_sec
* 1000)) * 1000;
165 if (detect_input_pending()) return(Qnil
);
166 redisplay_preserve_echo_area ();
168 * Check for queued keyboard input/mouse hits again
169 * (A bit screen update can take some time!)
171 if (detect_input_pending()) return(Qnil
);
172 select(1,&waitmask
,0,0,&Timeout
);
173 if (detect_input_pending()) return(Qnil
);
178 * Sun sleep-for (allows a shorter interval than the regular sleep-for)
180 DEFUN ("sleep-for-millisecs",
181 Fsleep_for_millisecs
,
182 Ssleep_for_millisecs
, 1, 1, 0,
183 "Pause, without updating display, for ARG milliseconds.")
190 useconds
= XINT(n
) * 1000;
195 DEFUN ("update-display", Fupdate_display
, Supdate_display
, 0, 0, 0,
196 "Perform redisplay.")
199 redisplay_preserve_echo_area ();
205 * Change the Sun mouse icon
207 DEFUN ("sun-change-cursor-icon",
208 Fsun_change_cursor_icon
,
209 Ssun_change_cursor_icon
, 1, 1, 0,
210 "Change the Sun mouse cursor icon. ICON is a lisp vector whose 1st element\n\
211 is the X offset of the cursor hot-point, whose 2nd element is the Y offset\n\
212 of the cursor hot-point and whose 3rd element is the cursor pixel data\n\
213 expressed as a string. If ICON is nil then the original arrow cursor is used")
217 register unsigned char *cp
;
220 Lisp_Object X_Hot
, Y_Hot
, Data
;
224 * If the icon is null, we just restore the DefaultCursor
227 CurrentCursor
= DefaultCursor
;
230 * extract the data from the vector
232 CHECK_VECTOR (Icon
, 0);
233 if (XVECTOR(Icon
)->size
< 3) return(Qnil
);
234 X_Hot
= XVECTOR(Icon
)->contents
[0];
235 Y_Hot
= XVECTOR(Icon
)->contents
[1];
236 Data
= XVECTOR(Icon
)->contents
[2];
238 CHECK_NUMBER (X_Hot
, 0);
239 CHECK_NUMBER (Y_Hot
, 0);
240 CHECK_STRING (Data
, 0);
241 if (XSTRING(Data
)->size
!= 32) return(Qnil
);
243 * Setup the new cursor
245 NewCursor
.cur_xhot
= X_Hot
;
246 NewCursor
.cur_yhot
= Y_Hot
;
247 cp
= XSTRING(Data
)->data
;
251 *p
++ = (cp
[0] << 8) | cp
[1], cp
+= 2;
252 CurrentCursor
= NewCursor
;
254 win_setcursor(win_fd
, &CurrentCursor
);
259 * Interface for sunwindows selection
261 static Lisp_Object Current_Selection
;
264 sel_write (sel
, file
)
265 struct selection
*sel
;
268 fwrite (XSTRING (Current_Selection
)->data
, sizeof (char),
269 sel
->sel_items
, file
);
273 sel_clear (sel
, windowfd
)
274 struct selection
*sel
;
281 struct selection
*sel
;
287 Current_Selection
= make_string ("", 0);
288 if (sel
->sel_items
<= 0)
290 cp
= (char *) malloc(sel
->sel_items
);
291 if (cp
== (char *)0) {
292 error("malloc failed in sel_read");
295 n
= fread(cp
, sizeof(char), sel
->sel_items
, file
);
296 if (n
> sel
->sel_items
) {
297 error("fread botch in sel_read");
300 error("Error reading selection.");
304 * The shelltool select saves newlines as carriage returns,
305 * but emacs wants newlines.
307 for (i
= 0; i
< n
; i
++)
308 if (cp
[i
] == '\r') cp
[i
] = '\n';
310 Current_Selection
= make_string (cp
, n
);
316 * Set the window system "selection" to be the arg STRING
318 DEFUN ("sun-set-selection", Fsun_set_selection
, Ssun_set_selection
, 1, 1,
319 "sSet selection to: ",
320 "Set the current sunwindow selection to STRING.")
324 struct selection selection
;
326 CHECK_STRING (str
, 0);
327 Current_Selection
= str
;
330 selection
.sel_type
= SELTYPE_CHAR
;
331 selection
.sel_items
= XSTRING (str
)->size
;
332 selection
.sel_itembytes
= 1;
333 selection
.sel_pubflags
= 1;
334 selection_set(&selection
, sel_write
, sel_clear
, win_fd
);
338 * Stuff the current window system selection into the current buffer
340 DEFUN ("sun-get-selection", Fsun_get_selection
, Ssun_get_selection
, 0, 0, 0,
341 "Return the current sunwindows selection as a string.")
344 CHECK_GFX (Current_Selection
);
345 selection_get (sel_read
, win_fd
);
346 return (Current_Selection
);
349 Menu
sun_menu_create();
352 sun_item_create (Pair
)
355 /* In here, we depend on Lisp supplying zero terminated strings in the data*/
356 /* so we can just pass the pointers, and not recopy anything */
363 if (!CONSP(Pair
)) wrong_type_argument(Qlistp
, Pair
);
365 CHECK_STRING(String
, 0);
367 if(XTYPE(Value
) == Lisp_Symbol
)
368 Value
= XSYMBOL(Value
)->value
;
369 if(XTYPE(Value
) == Lisp_Vector
) {
370 submenu
= sun_menu_create (Value
);
371 menu_item
= menu_create_item
372 (MENU_RELEASE
, MENU_PULLRIGHT_ITEM
, XSTRING(String
)->data
, submenu
, 0);
374 menu_item
= menu_create_item
375 (MENU_RELEASE
, MENU_STRING_ITEM
, XSTRING(String
)->data
, Value
, 0);
381 sun_menu_create (Vector
)
386 CHECK_VECTOR(Vector
,0);
388 for(i
= 0; i
< XVECTOR(Vector
)->size
; i
++) {
389 menu_set (menu
, MENU_APPEND_ITEM
,
390 sun_item_create(XVECTOR(Vector
)->contents
[i
]), 0);
396 * If the first item of the menu has nil as its value, then make the
397 * item look like a label by inverting it and making it unselectable.
398 * Returns 1 if the label was made, 0 otherwise.
401 make_menu_label (menu
)
404 int made_label_p
= 0;
406 if (( menu_get(menu
, MENU_NITEMS
) > 0 ) && /* At least one item */
407 ((Lisp_Object
) menu_get(menu_get(menu
, MENU_NTH_ITEM
, 1),
408 MENU_VALUE
) == Qnil
)) {
409 menu_set(menu_get(menu
, MENU_NTH_ITEM
, 1),
411 MENU_FEEDBACK
, FALSE
,
419 * Do a pop-up menu and return the selected value
421 DEFUN ("sun-menu-internal",
423 Ssun_menu_internal
, 5, 5, 0,
424 "Set up a SunView pop-up menu and return the user's choice.\n\
425 Arguments WINDOW, X, Y, BUTTON, and MENU.\n\
426 *** User code should generally use sun-menu-evaluate ***\n\
428 Arguments WINDOW, X, Y, BUTTON, and MENU.\n\
429 Put MENU up in WINDOW at position X, Y.\n\
430 The BUTTON argument specifies the button to be released that selects an item:\n\
434 The MENU argument is a vector containing (STRING . VALUE) pairs.\n\
435 The VALUE of the selected item is returned.\n\
436 If the VALUE of the first pair is nil, then the first STRING will be used\n\
438 (window
, X_Position
, Y_Position
, Button
, MEnu
)
439 Lisp_Object window
, X_Position
, Y_Position
, Button
, MEnu
;
442 int button
, xpos
, ypos
;
444 Event
*event
= &event0
;
445 Lisp_Object Value
, Pair
;
447 CHECK_NUMBER(X_Position
, 0);
448 CHECK_NUMBER(Y_Position
, 1);
449 CHECK_LIVE_WINDOW(window
, 2);
450 CHECK_NUMBER(Button
, 3);
451 CHECK_VECTOR(MEnu
, 4);
455 xpos
= CtoSX (XWINDOW(window
)->left
+ XINT(X_Position
));
456 ypos
= CtoSY (XWINDOW(window
)->top
+ XINT(Y_Position
));
457 #ifdef Menu_Base_Kludge
458 {static Lisp_Object symbol
[2];
459 symbol
[0] = Fintern (sm_kludge_string
, Qnil
);
460 Pair
= Ffuncall (1, symbol
);
461 xpos
+= XINT (XCONS (Pair
)->cdr
);
462 ypos
+= XINT (XCONS (Pair
)->car
);
466 button
= XINT(Button
);
467 if(button
== 4) button
= 3;
468 event_set_id (event
, BUT(button
));
469 event_set_down (event
);
470 event_set_x (event
, xpos
);
471 event_set_y (event
, ypos
);
473 menu
= sun_menu_create(MEnu
);
474 make_menu_label(menu
);
476 #ifdef Menu_Base_Kludge
477 Value
= (Lisp_Object
) menu_show(menu
, Menu_Base_Frame
, event
, 0);
479 /* This confuses the notifier or something: */
480 Value
= (Lisp_Object
) menu_show_using_fd(menu
, win_fd
, event
, 0);
482 * Right button gets lost, and event sequencing or delivery gets mixed up
483 * So, until that gets fixed, we use this <Menu_Base_Frame> kludge:
488 return ((int)Value
? Value
: Qnil
);
497 #ifdef Menu_Base_Kludge
498 /* i'm just too lazy to re-write this into C code */
499 /* so we will call this elisp function from C */
500 sm_kludge_string
= make_pure_string ("sm::menu-kludge", 15);
501 #endif /* Menu_Base_Kludge */
503 defsubr(&Ssun_window_init
);
504 defsubr(&Ssit_for_millisecs
);
505 defsubr(&Ssleep_for_millisecs
);
506 defsubr(&Supdate_display
);
507 defsubr(&Ssun_change_cursor_icon
);
508 defsubr(&Ssun_set_selection
);
509 defsubr(&Ssun_get_selection
);
510 defsubr(&Ssun_menu_internal
);