Mercurial > hg > xemacs-beta
comparison src/device.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 9ee227acff29 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Generic device functions. | |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1994, 1995 Free Software Foundation, Inc. | |
4 Copyright (C) 1995, 1996 Ben Wing | |
5 | |
6 This file is part of XEmacs. | |
7 | |
8 XEmacs is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
10 Free Software Foundation; either version 2, or (at your option) any | |
11 later version. | |
12 | |
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with XEmacs; see the file COPYING. If not, write to | |
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
21 Boston, MA 02111-1307, USA. */ | |
22 | |
23 /* Synched up with: Not in FSF. */ | |
24 | |
25 /* Original version by Chuck Thompson; | |
26 rewritten and expanded by Ben Wing. */ | |
27 | |
28 #include <config.h> | |
29 #include "lisp.h" | |
30 | |
31 #include "buffer.h" | |
32 #include "console.h" | |
33 #include "device.h" | |
34 #include "elhash.h" | |
35 #include "events.h" | |
36 #include "faces.h" | |
37 #include "frame.h" | |
38 #include "keymap.h" | |
39 #include "redisplay.h" | |
40 #include "scrollbar.h" | |
41 #include "specifier.h" | |
42 #include "sysdep.h" | |
43 #include "window.h" | |
44 | |
45 #include "syssignal.h" | |
46 | |
47 /* Vdefault_device is the firstly-created non-stream device that's still | |
48 around. We don't really use it anywhere currently, but it might | |
49 be used for resourcing at some point. (Currently we use | |
50 Vdefault_x_device.) */ | |
51 Lisp_Object Vdefault_device; | |
52 | |
53 Lisp_Object Vcreate_device_hook, Vdelete_device_hook; | |
54 | |
55 /* Device classes */ | |
56 /* Qcolor defined in general.c */ | |
57 Lisp_Object Qgrayscale, Qmono; | |
58 | |
59 Lisp_Object Qdevicep, Qdevice_live_p; | |
60 Lisp_Object Qdelete_device; | |
61 Lisp_Object Qcreate_device_hook; | |
62 Lisp_Object Qdelete_device_hook; | |
63 | |
64 Lisp_Object Vdevice_class_list; | |
65 | |
66 MAC_DEFINE (struct device *, MTdevice_data) | |
67 | |
68 | |
69 static Lisp_Object mark_device (Lisp_Object, void (*) (Lisp_Object)); | |
70 static void print_device (Lisp_Object, Lisp_Object, int); | |
71 DEFINE_LRECORD_IMPLEMENTATION ("device", device, | |
72 mark_device, print_device, 0, 0, 0, | |
73 struct device); | |
74 | |
75 static Lisp_Object | |
76 mark_device (Lisp_Object obj, void (*markobj) (Lisp_Object)) | |
77 { | |
78 struct device *d = XDEVICE (obj); | |
79 | |
80 ((markobj) (d->name)); | |
81 ((markobj) (d->connection)); | |
82 ((markobj) (d->canon_connection)); | |
83 ((markobj) (d->console)); | |
84 ((markobj) (d->_selected_frame)); | |
85 ((markobj) (d->frame_with_focus_real)); | |
86 ((markobj) (d->frame_with_focus_for_hooks)); | |
87 ((markobj) (d->frame_that_ought_to_have_focus)); | |
88 ((markobj) (d->device_class)); | |
89 ((markobj) (d->user_defined_tags)); | |
90 ((markobj) (d->pixel_to_glyph_cache.obj1)); | |
91 ((markobj) (d->pixel_to_glyph_cache.obj2)); | |
92 | |
93 ((markobj) (d->color_instance_cache)); | |
94 ((markobj) (d->font_instance_cache)); | |
95 ((markobj) (d->image_instance_cache)); | |
96 | |
97 if (d->devmeths) | |
98 { | |
99 ((markobj) (d->devmeths->symbol)); | |
100 MAYBE_DEVMETH (d, mark_device, (d, markobj)); | |
101 } | |
102 | |
103 return (d->frame_list); | |
104 } | |
105 | |
106 static void | |
107 print_device (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) | |
108 { | |
109 struct device *d = XDEVICE (obj); | |
110 char buf[256]; | |
111 | |
112 if (print_readably) | |
113 error ("printing unreadable object #<device %s 0x%x>", | |
114 string_data (XSTRING (d->name)), d->header.uid); | |
115 | |
116 sprintf (buf, "#<%s-device", !DEVICE_LIVE_P (d) ? "dead" : | |
117 DEVICE_TYPE_NAME (d)); | |
118 write_c_string (buf, printcharfun); | |
119 if (DEVICE_LIVE_P (d)) | |
120 { | |
121 write_c_string (" on ", printcharfun); | |
122 print_internal (DEVICE_CONNECTION (d), printcharfun, 1); | |
123 } | |
124 sprintf (buf, " 0x%x>", d->header.uid); | |
125 write_c_string (buf, printcharfun); | |
126 } | |
127 | |
128 | |
129 int | |
130 valid_device_class_p (Lisp_Object class) | |
131 { | |
132 return !NILP (memq_no_quit (class, Vdevice_class_list)); | |
133 } | |
134 | |
135 DEFUN ("valid-device-class-p", Fvalid_device_class_p, Svalid_device_class_p, | |
136 1, 1, 0 /* | |
137 Given a DEVICE-CLASS, return t if it is valid. | |
138 Valid classes are 'color, 'grayscale, and 'mono. | |
139 */ ) | |
140 (device_class) | |
141 Lisp_Object device_class; | |
142 { | |
143 if (valid_device_class_p (device_class)) | |
144 return Qt; | |
145 else | |
146 return Qnil; | |
147 } | |
148 | |
149 DEFUN ("device-class-list", Fdevice_class_list, Sdevice_class_list, | |
150 0, 0, 0 /* | |
151 Return a list of valid device classes. | |
152 */ ) | |
153 () | |
154 { | |
155 return Fcopy_sequence (Vdevice_class_list); | |
156 } | |
157 | |
158 static struct device * | |
159 allocate_device (Lisp_Object console) | |
160 { | |
161 Lisp_Object device = Qnil; | |
162 struct device *d = alloc_lcrecord (sizeof (struct device), lrecord_device); | |
163 struct gcpro gcpro1; | |
164 | |
165 zero_lcrecord (d); | |
166 | |
167 XSETDEVICE (device, d); | |
168 GCPRO1 (device); | |
169 | |
170 d->name = Qnil; | |
171 d->console = console; | |
172 d->connection = Qnil; | |
173 d->canon_connection = Qnil; | |
174 d->frame_list = Qnil; | |
175 d->_selected_frame = Qnil; | |
176 d->frame_with_focus_real = Qnil; | |
177 d->frame_with_focus_for_hooks = Qnil; | |
178 d->frame_that_ought_to_have_focus = Qnil; | |
179 d->device_class = Qnil; | |
180 d->user_defined_tags = Qnil; | |
181 d->pixel_to_glyph_cache.obj1 = Qnil; | |
182 d->pixel_to_glyph_cache.obj2 = Qnil; | |
183 | |
184 d->infd = d->outfd = -1; | |
185 | |
186 /* #### is 20 reasonable? */ | |
187 d->color_instance_cache = make_lisp_hashtable (20, HASHTABLE_KEY_WEAK, | |
188 HASHTABLE_EQUAL); | |
189 d->font_instance_cache = make_lisp_hashtable (20, HASHTABLE_KEY_WEAK, | |
190 HASHTABLE_EQUAL); | |
191 /* | |
192 Note that the image instance cache is actually bi-level. | |
193 See device.h. We use a low number here because most of the | |
194 time there aren't very many diferent masks that will be used. | |
195 */ | |
196 d->image_instance_cache = make_lisp_hashtable (5, HASHTABLE_NONWEAK, | |
197 HASHTABLE_EQ); | |
198 | |
199 UNGCPRO; | |
200 return d; | |
201 } | |
202 | |
203 struct device * | |
204 decode_device (Lisp_Object device) | |
205 { | |
206 if (NILP (device)) | |
207 device = Fselected_device (Qnil); | |
208 /* quietly accept frames for the device arg */ | |
209 if (FRAMEP (device)) | |
210 device = FRAME_DEVICE (decode_frame (device)); | |
211 CHECK_LIVE_DEVICE (device); | |
212 return XDEVICE (device); | |
213 } | |
214 | |
215 Lisp_Object | |
216 make_device (struct device *d) | |
217 { | |
218 Lisp_Object device = Qnil; | |
219 XSETDEVICE (device, d); | |
220 return device; | |
221 } | |
222 | |
223 DEFUN ("dfw-device", Fdfw_device, Sdfw_device, 1, 1, 0 /* | |
224 Given a device, frame, or window, return the associated device. | |
225 Return nil otherwise. | |
226 */ ) | |
227 (obj) | |
228 Lisp_Object obj; | |
229 { | |
230 return DFW_DEVICE (obj); | |
231 } | |
232 | |
233 | |
234 DEFUN ("selected-device", Fselected_device, Sselected_device, 0, 1, 0 /* | |
235 Return the device which is currently active. | |
236 If optional CONSOLE is non-nil, return the device that would be currently | |
237 active if CONSOLE were the selected console. | |
238 */ ) | |
239 (console) | |
240 Lisp_Object console; | |
241 { | |
242 if (NILP (console) && NILP (Vselected_console)) | |
243 return Qnil; /* happens early in temacs */ | |
244 return CONSOLE_SELECTED_DEVICE (decode_console (console)); | |
245 } | |
246 | |
247 /* Called from selected_frame_1(), called from Fselect_window() */ | |
248 void | |
249 select_device_1 (Lisp_Object device) | |
250 { | |
251 struct device *dev = XDEVICE (device); | |
252 Lisp_Object old_selected_device = Fselected_device (Qnil); | |
253 | |
254 if (EQ (device, old_selected_device)) | |
255 return; | |
256 | |
257 /* now select the device's console */ | |
258 CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (dev))) = device; | |
259 select_console_1 (DEVICE_CONSOLE (dev)); | |
260 } | |
261 | |
262 DEFUN ("select-device", Fselect_device, Sselect_device, 1, 1, 0 /* | |
263 Select the device DEVICE. | |
264 Subsequent editing commands apply to its console, selected frame, | |
265 and selected window. | |
266 The selection of DEVICE lasts until the next time the user does | |
267 something to select a different device, or until the next time this | |
268 function is called. | |
269 */ ) | |
270 (device) | |
271 Lisp_Object device; | |
272 { | |
273 CHECK_LIVE_DEVICE (device); | |
274 | |
275 /* select the device's selected frame's selected window. This will call | |
276 selected_frame_1()->selected_device_1()->selected_console_1(). */ | |
277 if (!NILP (DEVICE_SELECTED_FRAME (XDEVICE (device)))) | |
278 Fselect_window (FRAME_SELECTED_WINDOW | |
279 (XFRAME (DEVICE_SELECTED_FRAME (XDEVICE (device))))); | |
280 else | |
281 error ("Can't select a device with no frames"); | |
282 return Qnil; | |
283 } | |
284 | |
285 void | |
286 set_device_selected_frame (struct device *d, Lisp_Object frame) | |
287 { | |
288 if (!NILP (frame) && !FRAME_MINIBUF_ONLY_P (XFRAME (frame))) | |
289 set_console_last_nonminibuf_frame (XCONSOLE (DEVICE_CONSOLE (d)), frame); | |
290 d->_selected_frame = frame; | |
291 } | |
292 | |
293 DEFUN ("set-device-selected-frame", Fset_device_selected_frame, | |
294 Sset_device_selected_frame, 2, 2, 0 /* | |
295 Set the selected frame of device object DEVICE to FRAME. | |
296 If DEVICE is nil, the selected device is used. | |
297 If DEVICE is the selected device, this makes FRAME the selected frame. | |
298 */ ) | |
299 (device, frame) | |
300 Lisp_Object device, frame; | |
301 { | |
302 XSETDEVICE (device, decode_device (device)); | |
303 CHECK_LIVE_FRAME (frame); | |
304 | |
305 if (! EQ (device, FRAME_DEVICE (XFRAME (frame)))) | |
306 error ("In `set-device-selected-frame', FRAME is not on DEVICE"); | |
307 | |
308 if (EQ (device, Fselected_device (Qnil))) | |
309 return Fselect_frame (frame); | |
310 | |
311 set_device_selected_frame (XDEVICE (device), frame); | |
312 return frame; | |
313 } | |
314 | |
315 DEFUN ("devicep", Fdevicep, Sdevicep, 1, 1, 0 /* | |
316 Return non-nil if OBJECT is a device. | |
317 */ ) | |
318 (object) | |
319 Lisp_Object object; | |
320 { | |
321 if (!DEVICEP (object)) | |
322 return Qnil; | |
323 return Qt; | |
324 } | |
325 | |
326 DEFUN ("device-live-p", Fdevice_live_p, Sdevice_live_p, 1, 1, 0 /* | |
327 Return non-nil if OBJECT is a device that has not been deleted. | |
328 */ ) | |
329 (object) | |
330 Lisp_Object object; | |
331 { | |
332 if (!DEVICEP (object) || !DEVICE_LIVE_P (XDEVICE (object))) | |
333 return Qnil; | |
334 return Qt; | |
335 } | |
336 | |
337 DEFUN ("device-name", Fdevice_name, Sdevice_name, 0, 1, 0 /* | |
338 Return the name of the specified device. | |
339 DEVICE defaults to the selected device if omitted. | |
340 */ ) | |
341 (device) | |
342 Lisp_Object device; | |
343 { | |
344 return DEVICE_NAME (decode_device (device)); | |
345 } | |
346 | |
347 DEFUN ("device-connection", Fdevice_connection, Sdevice_connection, 0, 1, 0 /* | |
348 Return the connection of the specified device. | |
349 DEVICE defaults to the selected device if omitted. | |
350 */ ) | |
351 (device) | |
352 Lisp_Object device; | |
353 { | |
354 return DEVICE_CONNECTION (decode_device (device)); | |
355 } | |
356 | |
357 DEFUN ("device-console", Fdevice_console, Sdevice_console, 0, 1, 0 /* | |
358 Return the console of the specified device. | |
359 DEVICE defaults to the selected device if omitted. | |
360 */ ) | |
361 (device) | |
362 Lisp_Object device; | |
363 { | |
364 return DEVICE_CONSOLE (decode_device (device)); | |
365 } | |
366 | |
367 #ifdef HAVE_X_WINDOWS | |
368 extern Lisp_Object Vdefault_x_device; | |
369 #endif | |
370 #ifdef HAVE_NEXTSTEP | |
371 extern Lisp_Object Vdefault_ns_device; | |
372 #endif | |
373 | |
374 #ifdef HAVE_X_WINDOWS | |
375 | |
376 static void | |
377 init_global_resources (struct device *d) | |
378 { | |
379 init_global_faces (d); | |
380 #ifdef HAVE_SCROLLBARS | |
381 init_global_scrollbars (d); | |
382 #endif | |
383 #ifdef HAVE_TOOLBARS | |
384 init_global_toolbars (d); | |
385 #endif | |
386 } | |
387 | |
388 #endif | |
389 | |
390 static void | |
391 init_device_resources (struct device *d) | |
392 { | |
393 init_device_faces (d); | |
394 #ifdef HAVE_SCROLLBARS | |
395 init_device_scrollbars (d); | |
396 #endif | |
397 #ifdef HAVE_TOOLBARS | |
398 init_device_toolbars (d); | |
399 #endif | |
400 } | |
401 | |
402 static Lisp_Object | |
403 semi_canonicalize_device_connection (struct console_methods *meths, | |
404 Lisp_Object name, Error_behavior errb) | |
405 { | |
406 return CONTYPE_METH_OR_GIVEN (meths, semi_canonicalize_device_connection, | |
407 (name, errb), name); | |
408 } | |
409 | |
410 static Lisp_Object | |
411 canonicalize_device_connection (struct console_methods *meths, | |
412 Lisp_Object name, Error_behavior errb) | |
413 { | |
414 return CONTYPE_METH_OR_GIVEN (meths, canonicalize_device_connection, | |
415 (name, errb), name); | |
416 } | |
417 | |
418 static Lisp_Object | |
419 find_device_of_type (struct console_methods *meths, Lisp_Object canon) | |
420 { | |
421 Lisp_Object devcons, concons; | |
422 | |
423 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
424 { | |
425 Lisp_Object device = XCAR (devcons); | |
426 | |
427 if (EQ (CONMETH_TYPE (meths), DEVICE_TYPE (XDEVICE (device))) | |
428 && !NILP (Fequal (DEVICE_CANON_CONNECTION (XDEVICE (device)), | |
429 canon))) | |
430 return device; | |
431 } | |
432 | |
433 return Qnil; | |
434 } | |
435 | |
436 DEFUN ("find-device", Ffind_device, Sfind_device, 1, 2, 0 /* | |
437 Look for an existing device attached to connection CONNECTION. | |
438 Return the device if found; otherwise, return nil. | |
439 | |
440 If TYPE is specified, only return devices of that type; otherwise, | |
441 return devices of any type. (It is possible, although unlikely, | |
442 that two devices of different types could have the same connection | |
443 name; in such a case, the first device found is returned.) | |
444 */ ) | |
445 (connection, type) | |
446 Lisp_Object connection, type; | |
447 { | |
448 Lisp_Object canon = Qnil; | |
449 struct gcpro gcpro1; | |
450 | |
451 GCPRO1 (canon); | |
452 | |
453 if (!NILP (type)) | |
454 { | |
455 struct console_methods *conmeths = decode_console_type (type, ERROR_ME); | |
456 canon = canonicalize_device_connection (conmeths, connection, | |
457 ERROR_ME_NOT); | |
458 if (UNBOUNDP (canon)) | |
459 RETURN_UNGCPRO (Qnil); | |
460 | |
461 RETURN_UNGCPRO (find_device_of_type (conmeths, canon)); | |
462 } | |
463 else | |
464 { | |
465 int i; | |
466 | |
467 for (i = 0; i < Dynarr_length (the_console_type_entry_dynarr); i++) | |
468 { | |
469 struct console_methods *conmeths = | |
470 Dynarr_at (the_console_type_entry_dynarr, i).meths; | |
471 canon = canonicalize_device_connection (conmeths, connection, | |
472 ERROR_ME_NOT); | |
473 if (!UNBOUNDP (canon)) | |
474 { | |
475 Lisp_Object device = find_device_of_type (conmeths, canon); | |
476 if (!NILP (device)) | |
477 RETURN_UNGCPRO (device); | |
478 } | |
479 } | |
480 | |
481 RETURN_UNGCPRO (Qnil); | |
482 } | |
483 } | |
484 | |
485 DEFUN ("get-device", Fget_device, Sget_device, 1, 2, 0 /* | |
486 Look for an existing device attached to connection CONNECTION. | |
487 Return the device if found; otherwise, signal an error. | |
488 | |
489 If TYPE is specified, only return devices of that type; otherwise, | |
490 return devices of any type. (It is possible, although unlikely, | |
491 that two devices of different types could have the same connection | |
492 name; in such a case, the first device found is returned.) | |
493 */ ) | |
494 (connection, type) | |
495 Lisp_Object connection, type; | |
496 { | |
497 Lisp_Object device = Ffind_device (connection, type); | |
498 if (NILP (device)) | |
499 { | |
500 if (NILP (type)) | |
501 signal_simple_error ("No such device", connection); | |
502 else | |
503 signal_simple_error_2 ("No such device", type, connection); | |
504 } | |
505 return device; | |
506 } | |
507 | |
508 DEFUN ("make-device", Fmake_device, Smake_device, 2, 3, 0 /* | |
509 Create a new device of type TYPE, attached to connection CONNECTION. | |
510 | |
511 The valid values for CONNECTION are device-specific; however, | |
512 CONNECTION is generally a string. (Specifically, for X devices, | |
513 CONNECTION should be a display specification such as "foo:0", and | |
514 for TTY devices, CONNECTION should be the filename of a TTY device | |
515 file, such as "/dev/ttyp4", or nil to refer to XEmacs' standard | |
516 input/output.) | |
517 | |
518 PROPS, if specified, should be a plist of properties controlling | |
519 device creation. | |
520 | |
521 If CONNECTION specifies an already-existing device connection, that | |
522 device is simply returned; no new device is created, and PROPS | |
523 have no effect. | |
524 */ ) | |
525 (type, connection, props) | |
526 Lisp_Object type, connection, props; | |
527 { | |
528 /* This function can GC */ | |
529 struct device *d; | |
530 struct console *con; | |
531 Lisp_Object device = Qnil; | |
532 Lisp_Object console = Qnil; | |
533 Lisp_Object name = Qnil; | |
534 struct console_methods *conmeths; | |
535 | |
536 struct gcpro gcpro1, gcpro2, gcpro3; | |
537 #ifdef HAVE_X_WINDOWS | |
538 /* #### icky-poo. If this is the first X device we are creating, | |
539 then retrieve the global face resources. We have to do it | |
540 here, at the same time as (or just before) the device face | |
541 resources are retrieved; specifically, it needs to be done | |
542 after the device has been created but before any frames have | |
543 been popped up or much anything else has been done. It's | |
544 possible for other devices to specify different global | |
545 resources (there's a property on each X server's root window | |
546 that holds some resources); tough luck for the moment. | |
547 | |
548 This is a nasty violation of device independence, but | |
549 there's not a whole lot I can figure out to do about it. | |
550 The real problem is that the concept of resources is not | |
551 generalized away from X. Similar resource-related | |
552 device-independence violations occur in faces.el. */ | |
553 int first_x_device = NILP (Vdefault_x_device) && EQ (type, Qx); | |
554 #endif | |
555 | |
556 GCPRO3 (device, console, name); | |
557 | |
558 conmeths = decode_console_type (type, ERROR_ME_NOT); | |
559 if (!conmeths) | |
560 signal_simple_error ("Invalid device type", type); | |
561 | |
562 device = Ffind_device (connection, type); | |
563 if (!NILP (device)) | |
564 RETURN_UNGCPRO (device); | |
565 | |
566 name = Fplist_get (props, Qname, Qnil); | |
567 | |
568 { | |
569 Lisp_Object conconnect = | |
570 CONTYPE_METH_OR_GIVEN (conmeths, | |
571 device_to_console_connection, | |
572 (connection, ERROR_ME), | |
573 connection); | |
574 console = create_console (name, type, conconnect, props); | |
575 } | |
576 | |
577 con = XCONSOLE (console); | |
578 d = allocate_device (console); | |
579 XSETDEVICE (device, d); | |
580 | |
581 d->devmeths = con->conmeths; | |
582 | |
583 DEVICE_NAME (d) = name; | |
584 DEVICE_CONNECTION (d) = semi_canonicalize_device_connection (conmeths, | |
585 connection, | |
586 ERROR_ME); | |
587 DEVICE_CANON_CONNECTION (d) = canonicalize_device_connection (conmeths, | |
588 connection, | |
589 ERROR_ME); | |
590 | |
591 MAYBE_DEVMETH (d, init_device, (d, props)); | |
592 | |
593 /* Do it this way so that the device list is in order of creation */ | |
594 con->device_list = nconc2 (con->device_list, Fcons (device, Qnil)); | |
595 RESET_CHANGED_SET_FLAGS; | |
596 if (NILP (Vdefault_device) || DEVICE_STREAM_P (XDEVICE (Vdefault_device))) | |
597 Vdefault_device = device; | |
598 | |
599 init_device_sound (d); | |
600 #ifdef HAVE_X_WINDOWS | |
601 if (first_x_device) | |
602 init_global_resources (d); | |
603 #endif | |
604 init_device_resources (d); | |
605 | |
606 MAYBE_DEVMETH (d, finish_init_device, (d, props)); | |
607 | |
608 /* If this is the first device on the console, make it the selected one. */ | |
609 if (NILP (CONSOLE_SELECTED_DEVICE (con))) | |
610 CONSOLE_SELECTED_DEVICE (con) = device; | |
611 | |
612 /* #### the following should trap errors. */ | |
613 setup_device_initial_specifier_tags (d); | |
614 | |
615 UNGCPRO; | |
616 return device; | |
617 } | |
618 | |
619 /* find a device other than the selected one. Prefer non-stream | |
620 devices over stream devices. Maybe stay on the same console. */ | |
621 | |
622 static Lisp_Object | |
623 find_other_device (Lisp_Object device, int on_same_console) | |
624 { | |
625 Lisp_Object devcons = Qnil, concons = Qnil; | |
626 Lisp_Object console = DEVICE_CONSOLE (XDEVICE (device)); | |
627 | |
628 /* look for a non-stream device */ | |
629 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
630 { | |
631 Lisp_Object dev = XCAR (devcons); | |
632 if (on_same_console && !EQ (console, DEVICE_CONSOLE (XDEVICE (dev)))) | |
633 continue; | |
634 if (!DEVICE_STREAM_P (XDEVICE (dev)) && !EQ (dev, device) && | |
635 !NILP (DEVICE_SELECTED_FRAME (XDEVICE (dev)))) | |
636 goto double_break_1; | |
637 } | |
638 | |
639 double_break_1: | |
640 if (!NILP (devcons)) | |
641 return XCAR (devcons); | |
642 | |
643 /* OK, now look for a stream device */ | |
644 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
645 { | |
646 Lisp_Object dev = XCAR (devcons); | |
647 if (on_same_console && !EQ (console, DEVICE_CONSOLE (XDEVICE (dev)))) | |
648 continue; | |
649 if (!EQ (dev, device) && !NILP (DEVICE_SELECTED_FRAME (XDEVICE (dev)))) | |
650 goto double_break_2; | |
651 } | |
652 double_break_2: | |
653 if (!NILP (devcons)) | |
654 return XCAR (devcons); | |
655 | |
656 /* Sorry, there ain't none */ | |
657 return Qnil; | |
658 } | |
659 | |
660 static int | |
661 find_nonminibuffer_frame_not_on_device_predicate (Lisp_Object frame, | |
662 void *closure) | |
663 { | |
664 Lisp_Object device; | |
665 | |
666 VOID_TO_LISP (device, closure); | |
667 if (FRAME_MINIBUF_ONLY_P (XFRAME (frame))) | |
668 return 0; | |
669 if (EQ (device, FRAME_DEVICE (XFRAME (frame)))) | |
670 return 0; | |
671 return 1; | |
672 } | |
673 | |
674 Lisp_Object | |
675 find_nonminibuffer_frame_not_on_device (Lisp_Object device) | |
676 { | |
677 return find_some_frame (find_nonminibuffer_frame_not_on_device_predicate, | |
678 LISP_TO_VOID (device)); | |
679 } | |
680 | |
681 | |
682 /* Delete device D. | |
683 | |
684 If FORCE is non-zero, allow deletion of the only frame. | |
685 | |
686 If CALLED_FROM_DELETE_CONSOLE is non-zero, then, if | |
687 deleting the last device on a console, just delete it, | |
688 instead of calling `delete-console'. | |
689 | |
690 If FROM_IO_ERROR is non-zero, then the device is gone due | |
691 to an I/O error. This affects what happens if we exit | |
692 (we do an emergency exit instead of `save-buffers-kill-emacs'.) | |
693 */ | |
694 | |
695 void | |
696 delete_device_internal (struct device *d, int force, | |
697 int called_from_delete_console, | |
698 int from_io_error) | |
699 { | |
700 /* This function can GC */ | |
701 struct console *c; | |
702 Lisp_Object device = Qnil; | |
703 struct gcpro gcpro1; | |
704 | |
705 /* OK to delete an already-deleted device. */ | |
706 if (!DEVICE_LIVE_P (d)) | |
707 return; | |
708 | |
709 XSETDEVICE (device, d); | |
710 GCPRO1 (device); | |
711 | |
712 c = XCONSOLE (DEVICE_CONSOLE (d)); | |
713 | |
714 if (!called_from_delete_console) | |
715 { | |
716 int delete_console = 0; | |
717 /* If we're deleting the only device on the console, | |
718 delete the console. */ | |
719 if ((XINT (Flength (CONSOLE_DEVICE_LIST (c))) == 1) | |
720 /* if we just created the device, it might not be listed, | |
721 or something ... */ | |
722 && !NILP (memq_no_quit (device, CONSOLE_DEVICE_LIST (c)))) | |
723 delete_console = 1; | |
724 /* Or if there aren't any nonminibuffer frames that would be | |
725 left, delete the console (this will make XEmacs exit). */ | |
726 else if (NILP (find_nonminibuffer_frame_not_on_device (device))) | |
727 delete_console = 1; | |
728 | |
729 if (delete_console) | |
730 { | |
731 delete_console_internal (c, force, 0, from_io_error); | |
732 UNGCPRO; | |
733 return; | |
734 } | |
735 } | |
736 | |
737 reset_one_device (d); | |
738 | |
739 { | |
740 Lisp_Object frmcons; | |
741 | |
742 /* First delete all frames without their own minibuffers, | |
743 to avoid errors coming from attempting to delete a frame | |
744 that is a surrogate for another frame. */ | |
745 DEVICE_FRAME_LOOP (frmcons, d) | |
746 { | |
747 struct frame *f = XFRAME (XCAR (frmcons)); | |
748 /* delete_frame_internal() might do anything such as run hooks, | |
749 so be defensive. */ | |
750 if (FRAME_LIVE_P (f) && !FRAME_HAS_MINIBUF_P (f)) | |
751 delete_frame_internal (f, 1, 1, from_io_error); | |
752 | |
753 if (!DEVICE_LIVE_P (d)) /* make sure the delete-*-hook didn't | |
754 go ahead and delete anything */ | |
755 { | |
756 UNGCPRO; | |
757 return; | |
758 } | |
759 } | |
760 | |
761 /* #### This should probably be a device method but it is time for | |
762 19.14 to go out the door. */ | |
763 #ifdef HAVE_X_WINDOWS | |
764 /* Next delete all frames which have the popup property to avoid | |
765 deleting a child after its parent. */ | |
766 DEVICE_FRAME_LOOP (frmcons, d) | |
767 { | |
768 struct frame *f = XFRAME (XCAR (frmcons)); | |
769 | |
770 if (FRAME_LIVE_P (f)) | |
771 { | |
772 Lisp_Object popup = Fframe_property (XCAR (frmcons), Qpopup, Qnil); | |
773 if (!NILP (popup)) | |
774 delete_frame_internal (f, 1, 1, from_io_error); | |
775 | |
776 if (!DEVICE_LIVE_P (d)) /* make sure the delete-*-hook didn't | |
777 go ahead and delete anything */ | |
778 { | |
779 UNGCPRO; | |
780 return; | |
781 } | |
782 } | |
783 } | |
784 #endif /* HAVE_X_WINDOWS */ | |
785 | |
786 DEVICE_FRAME_LOOP (frmcons, d) | |
787 { | |
788 struct frame *f = XFRAME (XCAR (frmcons)); | |
789 /* delete_frame_internal() might do anything such as run hooks, | |
790 so be defensive. */ | |
791 if (FRAME_LIVE_P (f)) | |
792 delete_frame_internal (f, 1, 1, from_io_error); | |
793 | |
794 if (!DEVICE_LIVE_P (d)) /* make sure the delete-*-hook didn't | |
795 go ahead and delete anything */ | |
796 { | |
797 UNGCPRO; | |
798 return; | |
799 } | |
800 } | |
801 } | |
802 | |
803 set_device_selected_frame (d, Qnil); | |
804 | |
805 /* try to select another device */ | |
806 | |
807 if (EQ (device, Fselected_device (DEVICE_CONSOLE (d)))) | |
808 { | |
809 Lisp_Object other_dev = find_other_device (device, 1); | |
810 if (!NILP (other_dev)) | |
811 Fselect_device (other_dev); | |
812 } | |
813 | |
814 if (EQ (device, Vdefault_device)) | |
815 Vdefault_device = find_other_device (device, 0); | |
816 | |
817 MAYBE_DEVMETH (d, delete_device, (d)); | |
818 | |
819 CONSOLE_DEVICE_LIST (c) = delq_no_quit (device, CONSOLE_DEVICE_LIST (c)); | |
820 RESET_CHANGED_SET_FLAGS; | |
821 d->devmeths = dead_console_methods; | |
822 UNGCPRO; | |
823 } | |
824 | |
825 /* delete a device as a result of an I/O error. Called from | |
826 an enqueued magic-eval event. */ | |
827 | |
828 void | |
829 io_error_delete_device (Lisp_Object device) | |
830 { | |
831 delete_device_internal (XDEVICE (device), 1, 0, 1); | |
832 } | |
833 | |
834 DEFUN ("delete-device", Fdelete_device, Sdelete_device, 1, 2, 0 /* | |
835 Delete DEVICE, permanently eliminating it from use. | |
836 Normally, you cannot delete the last non-minibuffer-only frame (you must | |
837 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional | |
838 second argument FORCE is non-nil, you can delete the last frame. (This | |
839 will automatically call `save-buffers-kill-emacs'.) | |
840 */ ) | |
841 (device, force) | |
842 Lisp_Object device, force; | |
843 { | |
844 CHECK_DEVICE (device); | |
845 delete_device_internal (XDEVICE (device), !NILP (force), 0, 0); | |
846 return Qnil; | |
847 } | |
848 | |
849 DEFUN ("device-frame-list", Fdevice_frame_list, Sdevice_frame_list, | |
850 0, 1, 0 /* | |
851 Return a list of all frames on DEVICE. | |
852 If DEVICE is nil, the selected device will be used. | |
853 */ ) | |
854 (device) | |
855 Lisp_Object device; | |
856 { | |
857 return Fcopy_sequence (DEVICE_FRAME_LIST (decode_device (device))); | |
858 } | |
859 | |
860 DEFUN ("device-class", Fdevice_class, Sdevice_class, | |
861 0, 1, 0 /* | |
862 Return the class (color behavior) of DEVICE. | |
863 This will be one of 'color, 'grayscale, or 'mono. | |
864 */ ) | |
865 (device) | |
866 Lisp_Object device; | |
867 { | |
868 return DEVICE_CLASS (decode_device (device)); | |
869 } | |
870 | |
871 DEFUN ("set-device-class", Fset_device_class, Sset_device_class, | |
872 2, 2, 0 /* | |
873 Set the class (color behavior) of DEVICE. | |
874 CLASS should be one of 'color, 'grayscale, or 'mono. | |
875 This is only allowed on device such as TTY devices, where the color | |
876 behavior cannot necessarily be determined automatically. | |
877 */ ) | |
878 (device, class) | |
879 Lisp_Object device, class; | |
880 { | |
881 struct device *d = decode_device (device); | |
882 XSETDEVICE (device, d); | |
883 if (!DEVICE_TTY_P (d)) | |
884 signal_simple_error ("Cannot change the class of this device", device); | |
885 if (!EQ (class, Qcolor) && !EQ (class, Qmono) && !EQ (class, Qgrayscale)) | |
886 signal_simple_error ("Must be color, mono, or grayscale", class); | |
887 DEVICE_CLASS (d) = class; | |
888 return Qnil; | |
889 } | |
890 | |
891 DEFUN ("device-pixel-width", Fdevice_pixel_width, Sdevice_pixel_width, | |
892 0, 1, 0 /* | |
893 Return the width in pixels of DEVICE, or nil if unknown. | |
894 */ ) | |
895 (device) | |
896 Lisp_Object device; | |
897 { | |
898 struct device *d = decode_device (device); | |
899 int retval; | |
900 | |
901 retval = DEVMETH_OR_GIVEN (d, device_pixel_width, (d), 0); | |
902 if (retval <= 0) | |
903 return Qnil; | |
904 | |
905 return make_int (retval); | |
906 } | |
907 | |
908 DEFUN ("device-pixel-height", Fdevice_pixel_height, Sdevice_pixel_height, | |
909 0, 1, 0 /* | |
910 Return the height in pixels of DEVICE, or nil if unknown. | |
911 */ ) | |
912 (device) | |
913 Lisp_Object device; | |
914 { | |
915 struct device *d = decode_device (device); | |
916 int retval; | |
917 | |
918 retval = DEVMETH_OR_GIVEN (d, device_pixel_height, (d), 0); | |
919 if (retval <= 0) | |
920 return Qnil; | |
921 | |
922 return make_int (retval); | |
923 } | |
924 | |
925 DEFUN ("device-mm-width", Fdevice_mm_width, Sdevice_mm_width, | |
926 0, 1, 0 /* | |
927 Return the width in millimeters of DEVICE, or nil if unknown. | |
928 */ ) | |
929 (device) | |
930 Lisp_Object device; | |
931 { | |
932 struct device *d = decode_device (device); | |
933 int retval; | |
934 | |
935 retval = DEVMETH_OR_GIVEN (d, device_mm_width, (d), 0); | |
936 if (retval <= 0) | |
937 return Qnil; | |
938 | |
939 return make_int (retval); | |
940 } | |
941 | |
942 DEFUN ("device-mm-height", Fdevice_mm_height, Sdevice_mm_height, | |
943 0, 1, 0 /* | |
944 Return the height in millimeters of DEVICE, or nil if unknown. | |
945 */ ) | |
946 (device) | |
947 Lisp_Object device; | |
948 { | |
949 struct device *d = decode_device (device); | |
950 int retval; | |
951 | |
952 retval = DEVMETH_OR_GIVEN (d, device_mm_height, (d), 0); | |
953 if (retval <= 0) | |
954 return Qnil; | |
955 | |
956 return make_int (retval); | |
957 } | |
958 | |
959 DEFUN ("device-bitplanes", Fdevice_bitplanes, Sdevice_bitplanes, | |
960 0, 1, 0 /* | |
961 Return the number of bitplanes of DEVICE, or nil if unknown. | |
962 */ ) | |
963 (device) | |
964 Lisp_Object device; | |
965 { | |
966 struct device *d = decode_device (device); | |
967 int retval; | |
968 | |
969 retval = DEVMETH_OR_GIVEN (d, device_bitplanes, (d), 0); | |
970 if (retval <= 0) | |
971 return Qnil; | |
972 | |
973 return make_int (retval); | |
974 } | |
975 | |
976 DEFUN ("device-color-cells", Fdevice_color_cells, Sdevice_color_cells, | |
977 0, 1, 0 /* | |
978 Return the number of color cells of DEVICE, or nil if unknown. | |
979 */ ) | |
980 (device) | |
981 Lisp_Object device; | |
982 { | |
983 struct device *d = decode_device (device); | |
984 int retval; | |
985 | |
986 retval = DEVMETH_OR_GIVEN (d, device_color_cells, (d), 0); | |
987 if (retval <= 0) | |
988 return Qnil; | |
989 | |
990 return make_int (retval); | |
991 } | |
992 | |
993 DEFUN ("set-device-baud-rate", Fset_device_baud_rate, Sset_device_baud_rate, | |
994 2, 2, 0 /* | |
995 Set the output baud rate of DEVICE to RATE. | |
996 On most systems, changing this value will affect the amount of padding | |
997 and other strategic decisions made during redisplay. | |
998 */ ) | |
999 (device, rate) | |
1000 Lisp_Object device, rate; | |
1001 { | |
1002 CHECK_INT (rate); | |
1003 | |
1004 DEVICE_BAUD_RATE (decode_device (device)) = XINT (rate); | |
1005 | |
1006 return rate; | |
1007 } | |
1008 | |
1009 DEFUN ("device-baud-rate", Fdevice_baud_rate, Sdevice_baud_rate, | |
1010 0, 1, 0 /* | |
1011 Return the output baud rate of DEVICE. | |
1012 */ ) | |
1013 (device) | |
1014 Lisp_Object device; | |
1015 { | |
1016 return make_int (DEVICE_BAUD_RATE (decode_device (device))); | |
1017 } | |
1018 | |
1019 void | |
1020 handle_asynch_device_change (void) | |
1021 { | |
1022 int i; | |
1023 int old_asynch_device_change_pending = asynch_device_change_pending; | |
1024 for (i = 0; i < Dynarr_length (the_console_type_entry_dynarr); i++) | |
1025 { | |
1026 if (Dynarr_at (the_console_type_entry_dynarr, i).meths-> | |
1027 asynch_device_change_method) | |
1028 (Dynarr_at (the_console_type_entry_dynarr, i).meths-> | |
1029 asynch_device_change_method) (); | |
1030 } | |
1031 /* reset the flag to 0 unless another notification occurred while | |
1032 we were processing this one. Block SIGWINCH during this | |
1033 check to prevent a possible race condition. */ | |
1034 EMACS_BLOCK_SIGNAL (SIGWINCH); | |
1035 if (old_asynch_device_change_pending == asynch_device_change_pending) | |
1036 asynch_device_change_pending = 0; | |
1037 EMACS_UNBLOCK_SIGNAL (SIGWINCH); | |
1038 } | |
1039 | |
1040 void | |
1041 call_critical_lisp_code (struct device *d, Lisp_Object function, | |
1042 Lisp_Object object) | |
1043 { | |
1044 int old_gc_currently_forbidden = gc_currently_forbidden; | |
1045 Lisp_Object old_inhibit_quit = Vinhibit_quit; | |
1046 | |
1047 /* There's no reason to bother doing specbinds here, because if | |
1048 initialize-*-faces signals an error, emacs is going to crash | |
1049 immediately. | |
1050 */ | |
1051 gc_currently_forbidden = 1; | |
1052 Vinhibit_quit = Qt; | |
1053 LOCK_DEVICE (d); | |
1054 | |
1055 /* But it's useful to have an error handler; otherwise an infinite | |
1056 loop may result. */ | |
1057 if (!NILP (object)) | |
1058 call1_with_handler (Qreally_early_error_handler, function, object); | |
1059 else | |
1060 call0_with_handler (Qreally_early_error_handler, function); | |
1061 | |
1062 UNLOCK_DEVICE (d); | |
1063 Vinhibit_quit = old_inhibit_quit; | |
1064 gc_currently_forbidden = old_gc_currently_forbidden; | |
1065 } | |
1066 | |
1067 | |
1068 /************************************************************************/ | |
1069 /* initialization */ | |
1070 /************************************************************************/ | |
1071 | |
1072 void | |
1073 syms_of_device (void) | |
1074 { | |
1075 defsubr (&Svalid_device_class_p); | |
1076 defsubr (&Sdevice_class_list); | |
1077 | |
1078 defsubr (&Sdfw_device); | |
1079 defsubr (&Sselected_device); | |
1080 defsubr (&Sselect_device); | |
1081 defsubr (&Sset_device_selected_frame); | |
1082 defsubr (&Sdevicep); | |
1083 defsubr (&Sdevice_live_p); | |
1084 defsubr (&Sdevice_name); | |
1085 defsubr (&Sdevice_connection); | |
1086 defsubr (&Sdevice_console); | |
1087 defsubr (&Sfind_device); | |
1088 defsubr (&Sget_device); | |
1089 defsubr (&Smake_device); | |
1090 defsubr (&Sdelete_device); | |
1091 defsubr (&Sdevice_frame_list); | |
1092 defsubr (&Sdevice_class); | |
1093 defsubr (&Sset_device_class); | |
1094 defsubr (&Sdevice_pixel_width); | |
1095 defsubr (&Sdevice_pixel_height); | |
1096 defsubr (&Sdevice_mm_width); | |
1097 defsubr (&Sdevice_mm_height); | |
1098 defsubr (&Sdevice_bitplanes); | |
1099 defsubr (&Sdevice_color_cells); | |
1100 defsubr (&Sset_device_baud_rate); | |
1101 defsubr (&Sdevice_baud_rate); | |
1102 | |
1103 defsymbol (&Qdevicep, "devicep"); | |
1104 defsymbol (&Qdevice_live_p, "device-live-p"); | |
1105 defsymbol (&Qdelete_device, "delete-device"); | |
1106 | |
1107 defsymbol (&Qcreate_device_hook, "create-device-hook"); | |
1108 defsymbol (&Qdelete_device_hook, "delete-device-hook"); | |
1109 | |
1110 /* Qcolor defined in general.c */ | |
1111 defsymbol (&Qgrayscale, "grayscale"); | |
1112 defsymbol (&Qmono, "mono"); | |
1113 } | |
1114 | |
1115 void | |
1116 vars_of_device (void) | |
1117 { | |
1118 DEFVAR_LISP ("create-device-hook", &Vcreate_device_hook /* | |
1119 Function or functions to call when a device is created. | |
1120 One argument, the newly-created device. | |
1121 This is called after the first frame has been created, but before | |
1122 calling the `create-frame-hook'. | |
1123 Note that in general the device will not be selected. | |
1124 */ ); | |
1125 Vcreate_device_hook = Qnil; | |
1126 | |
1127 DEFVAR_LISP ("delete-device-hook", &Vdelete_device_hook /* | |
1128 Function or functions to call when a device is deleted. | |
1129 One argument, the to-be-deleted device. | |
1130 */ ); | |
1131 Vdelete_device_hook = Qnil; | |
1132 | |
1133 staticpro (&Vdefault_device); | |
1134 Vdefault_device = Qnil; | |
1135 | |
1136 asynch_device_change_pending = 0; | |
1137 | |
1138 Vdevice_class_list = list3 (Qcolor, Qgrayscale, Qmono); | |
1139 staticpro (&Vdevice_class_list); | |
1140 } |