04d7a8bb529db488f4928a5a7ef176107723163c
[sxemacs] / src / ui / device.c
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 SXEmacs
7
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
20
21
22 /* Synched up with: Not in FSF. */
23
24 /* Original version by Chuck Thompson;
25    rewritten and expanded by Ben Wing. */
26
27 #include <config.h>
28 #include "lisp.h"
29
30 #include "buffer.h"
31 #include "console.h"
32 #include "device.h"
33 #include "elhash.h"
34 #include "events/events.h"
35 #include "faces.h"
36 #include "frame.h"
37 #include "keymap.h"
38 #include "redisplay.h"
39 #include "specifier.h"
40 #include "sysdep.h"
41 #include "window.h"
42
43 #ifdef HAVE_SCROLLBARS
44 #include "scrollbar.h"
45 #endif
46
47 #include "syssignal.h"
48
49 /* Vdefault_device is the firstly-created non-stream device that's still
50    around.  We don't really use it anywhere currently, but it might
51    be used for resourcing at some point.  (Currently we use
52    Vdefault_x_device.) */
53 Lisp_Object Vdefault_device;
54
55 Lisp_Object Vcreate_device_hook, Vdelete_device_hook;
56
57 /* Device classes */
58 /* Qcolor defined in general.c */
59 Lisp_Object Qgrayscale, Qmono;
60
61 /* Device metrics symbols */
62 Lisp_Object
63     Qcolor_default, Qcolor_select, Qcolor_balloon, Qcolor_3d_face,
64     Qcolor_3d_light, Qcolor_3d_dark, Qcolor_menu, Qcolor_menu_highlight,
65     Qcolor_menu_button, Qcolor_menu_disabled, Qcolor_toolbar,
66     Qcolor_scrollbar, Qcolor_desktop, Qcolor_workspace, Qfont_default,
67     Qfont_menubar, Qfont_dialog, Qsize_cursor, Qsize_scrollbar,
68     Qsize_menu, Qsize_toolbar, Qsize_toolbar_button,
69     Qsize_toolbar_border, Qsize_icon, Qsize_icon_small, Qsize_device,
70     Qsize_workspace, Qoffset_workspace, Qsize_device_mm, Qdevice_dpi,
71     Qnum_bit_planes, Qnum_color_cells, Qmouse_buttons, Qswap_buttons,
72     Qshow_sounds, Qslow_device, Qsecurity;
73
74 Lisp_Object Qdevicep, Qdevice_live_p;
75 Lisp_Object Qcreate_device_hook;
76 Lisp_Object Qdelete_device_hook;
77 Lisp_Object Vdevice_class_list;
78 \f
79 static Lisp_Object mark_device(Lisp_Object obj)
80 {
81         struct device *d = XDEVICE(obj);
82
83         mark_object(d->name);
84         mark_object(d->connection);
85         mark_object(d->canon_connection);
86         mark_object(d->console);
87         mark_object(d->selected_frame);
88         mark_object(d->frame_with_focus_real);
89         mark_object(d->frame_with_focus_for_hooks);
90         mark_object(d->frame_that_ought_to_have_focus);
91         mark_object(d->device_class);
92         mark_object(d->user_defined_tags);
93         mark_object(d->pixel_to_glyph_cache.obj1);
94         mark_object(d->pixel_to_glyph_cache.obj2);
95
96         mark_object(d->color_instance_cache);
97         mark_object(d->font_instance_cache);
98 #ifdef MULE
99         mark_object(d->charset_font_cache);
100 #endif
101         mark_object(d->image_instance_cache);
102
103         if (d->devmeths) {
104                 mark_object(d->devmeths->symbol);
105                 MAYBE_DEVMETH(d, mark_device, (d));
106         }
107
108         return (d->frame_list);
109 }
110
111 static void
112 print_device(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
113 {
114         struct device *d = XDEVICE(obj);
115
116         if (print_readably)
117                 error("printing unreadable object #<device %s 0x%x>",
118                       XSTRING_DATA(d->name), d->header.uid);
119
120         write_fmt_string(printcharfun, "#<%s-device", 
121                          (!DEVICE_LIVE_P(d) ? "dead" :DEVICE_TYPE_NAME(d)));
122         if (DEVICE_LIVE_P(d) && !NILP(DEVICE_CONNECTION(d))) {
123                 write_c_string(" on ", printcharfun);
124                 print_internal(DEVICE_CONNECTION(d), printcharfun, 1);
125         }
126         write_fmt_str(printcharfun, " 0x%x>", d->header.uid);
127 }
128
129 DEFINE_LRECORD_IMPLEMENTATION("device", device,
130                               mark_device, print_device, 0, 0, 0, 0,
131                               struct device);
132 \f
133 int valid_device_class_p(Lisp_Object class)
134 {
135         return !NILP(memq_no_quit(class, Vdevice_class_list));
136 }
137
138 DEFUN("valid-device-class-p", Fvalid_device_class_p, 1, 1, 0,   /*
139 Given a DEVICE-CLASS, return t if it is valid.
140 Valid classes are 'color, 'grayscale, and 'mono.
141 */
142       (device_class))
143 {
144         return valid_device_class_p(device_class) ? Qt : Qnil;
145 }
146
147 DEFUN("device-class-list", Fdevice_class_list, 0, 0, 0, /*
148 Return a list of valid device classes.
149 */
150       ())
151 {
152         return Fcopy_sequence(Vdevice_class_list);
153 }
154
155 static struct device *allocate_device(Lisp_Object console)
156 {
157         Lisp_Object device;
158         struct device *d = alloc_lcrecord_type(struct device, &lrecord_device);
159         struct gcpro gcpro1;
160
161         zero_lcrecord(d);
162
163         XSETDEVICE(device, d);
164         GCPRO1(device);
165
166         d->name = Qnil;
167         d->console = console;
168         d->connection = Qnil;
169         d->canon_connection = Qnil;
170         d->frame_list = Qnil;
171         d->selected_frame = Qnil;
172         d->frame_with_focus_real = Qnil;
173         d->frame_with_focus_for_hooks = Qnil;
174         d->frame_that_ought_to_have_focus = Qnil;
175         d->device_class = Qnil;
176         d->user_defined_tags = Qnil;
177         d->pixel_to_glyph_cache.obj1 = Qnil;
178         d->pixel_to_glyph_cache.obj2 = Qnil;
179
180         d->infd = d->outfd = -1;
181
182         /* #### is 20 reasonable? */
183         d->color_instance_cache =
184             make_lisp_hash_table(20, HASH_TABLE_KEY_WEAK, HASH_TABLE_EQUAL);
185         d->font_instance_cache =
186             make_lisp_hash_table(20, HASH_TABLE_KEY_WEAK, HASH_TABLE_EQUAL);
187 #ifdef MULE
188         /* Note that the following table is bi-level. */
189         d->charset_font_cache =
190             make_lisp_hash_table(20, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
191 #endif
192         /*
193            Note that the image instance cache is actually bi-level.
194            See device.h.  We use a low number here because most of the
195            time there aren't very many different masks that will be used.
196          */
197         d->image_instance_cache =
198             make_lisp_hash_table(5, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
199
200         UNGCPRO;
201         return d;
202 }
203
204 struct device *decode_device(Lisp_Object device)
205 {
206         if (NILP(device))
207                 device = Fselected_device(Qnil);
208         /* quietly accept frames for the device arg */
209         else if (FRAMEP(device))
210                 device = FRAME_DEVICE(decode_frame(device));
211         CHECK_LIVE_DEVICE(device);
212         return XDEVICE(device);