Fix display of Arabic diacriticals on Windows, per bug #11860.
[bpt/emacs.git] / src / widget.c
CommitLineData
07bf635f 1/* The emacs frame widget.
acaf905b 2 Copyright (C) 1992-1993, 2000-2012 Free Software Foundation, Inc.
07bf635f
RS
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
07bf635f 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
07bf635f
RS
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
07bf635f
RS
18
19/* Emacs 19 face widget ported by Fred Pierresteguy */
20
ac26ca64
KH
21/* This file has been censored by the Communications Decency Act.
22 That law was passed under the guise of a ban on pornography, but
23 it bans far more than that. This file did not contain pornography,
24 but it was censored nonetheless.
25
26 For information on US government censorship of the Internet, and
27 what you can do to bring back freedom of the press, see the web
28 site http://www.vtw.org/
29 */
30
9e65ad77 31#include <config.h>
565620a5 32#include <stdio.h>
d7306fe6 33#include <setjmp.h>
07bf635f
RS
34#include "lisp.h"
35#include "xterm.h"
36
87a43646 37#include "keyboard.h"
07bf635f 38#include "frame.h"
dfcf069d 39#include "window.h"
07bf635f
RS
40
41#include "dispextern.h"
49fe12a9 42#include "blockinput.h"
07bf635f
RS
43
44#include <X11/StringDefs.h>
45#include <X11/IntrinsicP.h>
46#include <X11/cursorfont.h>
47#include "widgetprv.h"
65fbf4a3 48#include <X11/ObjectP.h>
07bf635f
RS
49#include <X11/Shell.h>
50#include <X11/ShellP.h>
69524b98 51#include "../lwlib/lwlib.h"
07bf635f 52
a5d3ec3f
GM
53#include <signal.h>
54#include "syssignal.h"
55
39d14c25
CY
56#include "character.h"
57#include "font.h"
58
07bf635f
RS
59/* This sucks: this is the first default that x-faces.el tries. This won't
60 be used unless neither the "Emacs.EmacsFrame" resource nor the
61 "Emacs.EmacsFrame" resource is set; the frame
62 may have the wrong default size if this font doesn't exist, but some other
63 font that x-faces.el does. The workaround is to specify some font in the
64 resource database; I don't know a solution other than duplicating the font-
65 searching code from x-faces.el in this file.
66
67 This also means that if "Emacs.EmacsFrame" is specified as a non-
68 existent font, then Xt is going to substitute "XtDefaultFont" for it,
69 which is a different size than this one. The solution for this is to
70 make x-faces.el try to use XtDefaultFont. The problem with that is that
71 XtDefaultFont is almost certainly variable-width.
72
73 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
74 */
75#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
76
77
ebd15611
DN
78static void EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2);
79static void EmacsFrameDestroy (Widget widget);
80static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs);
4475bec4 81static void EmacsFrameResize (Widget widget);
ebd15611
DN
82static Boolean EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2);
83static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result);
07bf635f
RS
84
85
86#undef XtOffset
87#define XtOffset(p_type,field) \
88 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
5e617bc2 89#define offset(field) XtOffset (EmacsFrame, emacs_frame.field)
07bf635f
RS
90
91static XtResource resources[] = {
5e617bc2 92 {XtNgeometry, XtCGeometry, XtRString, sizeof (String),
07bf635f 93 offset (geometry), XtRString, (XtPointer) 0},
5e617bc2 94 {XtNiconic, XtCIconic, XtRBoolean, sizeof (Boolean),
07bf635f
RS
95 offset (iconic), XtRImmediate, (XtPointer) False},
96
97 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
98 offset (frame), XtRImmediate, 0},
99
100 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
101 offset (minibuffer), XtRImmediate, (XtPointer)0},
102 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
103 offset (unsplittable), XtRImmediate, (XtPointer)0},
104 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
105 offset (internal_border_width), XtRImmediate, (XtPointer)4},
106 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
107 offset (interline), XtRImmediate, (XtPointer)0},
5e617bc2
JB
108 {XtNfont, XtCFont, XtRFontStruct, sizeof (struct font *),
109 offset (font),XtRString, DEFAULT_FACE_FONT},
110 {XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
111 offset (foreground_pixel), XtRString, "XtDefaultForeground"},
112 {XtNcursorColor, XtCForeground, XtRPixel, sizeof (Pixel),
113 offset (cursor_color), XtRString, "XtDefaultForeground"},
07bf635f
RS
114 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
115 offset (bar_cursor), XtRImmediate, (XtPointer)0},
116 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
117 offset (visual_bell), XtRImmediate, (XtPointer)0},
118 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
119 offset (bell_volume), XtRImmediate, (XtPointer)0},
120};
121
122#undef offset
123
124/*
125static XtActionsRec
126emacsFrameActionsTable [] = {
127 {"keypress", key_press},
128 {"focus_in", emacs_frame_focus_handler},
129 {"focus_out", emacs_frame_focus_handler},
130};
131
132static char
133emacsFrameTranslations [] = "\
134<KeyPress>: keypress()\n\
135<FocusIn>: focus_in()\n\
136<FocusOut>: focus_out()\n\
137";
138*/
139
4475bec4 140static EmacsFrameClassRec emacsFrameClassRec = {
07bf635f
RS
141 { /* core fields */
142 /* superclass */ &widgetClassRec,
143 /* class_name */ "EmacsFrame",
5e617bc2 144 /* widget_size */ sizeof (EmacsFrameRec),
07bf635f
RS
145 /* class_initialize */ 0,
146 /* class_part_initialize */ 0,
147 /* class_inited */ FALSE,
148 /* initialize */ EmacsFrameInitialize,
149 /* initialize_hook */ 0,
150 /* realize */ EmacsFrameRealize,
151 /* actions */ 0, /*emacsFrameActionsTable*/
152 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
153 /* resources */ resources,
5e617bc2 154 /* resource_count */ XtNumber (resources),
07bf635f
RS
155 /* xrm_class */ NULLQUARK,
156 /* compress_motion */ TRUE,
157 /* compress_exposure */ TRUE,
158 /* compress_enterleave */ TRUE,
159 /* visible_interest */ FALSE,
160 /* destroy */ EmacsFrameDestroy,
161 /* resize */ EmacsFrameResize,
162 /* expose */ XtInheritExpose,
163 /* set_values */ EmacsFrameSetValues,
164 /* set_values_hook */ 0,
165 /* set_values_almost */ XtInheritSetValuesAlmost,
166 /* get_values_hook */ 0,
167 /* accept_focus */ XtInheritAcceptFocus,
168 /* version */ XtVersion,
169 /* callback_private */ 0,
170 /* tm_table */ 0, /*emacsFrameTranslations*/
171 /* query_geometry */ EmacsFrameQueryGeometry,
172 /* display_accelerator */ XtInheritDisplayAccelerator,
173 /* extension */ 0
174 }
175};
176
177WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
178
179static void
ebd15611 180get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height)
07bf635f 181{
07bf635f 182 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
183 *pixel_width = FRAME_COLUMN_WIDTH (f);
184 *pixel_height = FRAME_LINE_HEIGHT (f);
07bf635f
RS
185}
186
187static void
ebd15611 188pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *char_width, int *char_height)
07bf635f
RS
189{
190 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
191 *char_width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, (int) pixel_width);
192 *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height);
07bf635f
RS
193}
194
195static void
ebd15611 196char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height)
07bf635f
RS
197{
198 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
199 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
200 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
07bf635f
RS
201}
202
203static void
ebd15611 204round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, Dimension *out_width, Dimension *out_height)
07bf635f
RS
205{
206 int char_width;
207 int char_height;
208 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
209 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
210}
211
212static Widget
ebd15611 213get_wm_shell (Widget w)
07bf635f
RS
214{
215 Widget wmshell;
216
217 for (wmshell = XtParent (w);
218 wmshell && !XtIsWMShell (wmshell);
219 wmshell = XtParent (wmshell));
220
221 return wmshell;
222}
223
ccce6056
GM
224#if 0 /* Currently not used. */
225
07bf635f 226static void
1dae0f0a 227mark_shell_size_user_specified (Widget wmshell)
07bf635f
RS
228{
229 if (! XtIsWMShell (wmshell)) abort ();
230 /* This is kind of sleazy, but I can't see how else to tell it to make it
231 mark the WM_SIZE_HINTS size as user specified when appropriate. */
232 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
233}
234
ccce6056
GM
235#endif
236
07bf635f
RS
237
238/* Can't have static frame locals because of some broken compilers.
239 Normally, initializing a variable like this doesn't work in emacs,
240 but it's ok in this file because it must come after lastfile (and
241 thus have its data not go into text space) because Xt needs to
242 write to initialized data objects too.
243 */
ccce6056 244#if 0
07bf635f 245static Boolean first_frame_p = True;
ccce6056 246#endif
07bf635f
RS
247
248static void
ebd15611 249set_frame_size (EmacsFrame ew)
07bf635f
RS
250{
251 /* The widget hierarchy is
252
253 argv[0] emacsShell pane Frame-NAME
254 ApplicationShell EmacsShell Paned EmacsFrame
255
256 We accept geometry specs in this order:
257
258 *Frame-NAME.geometry
259 *EmacsFrame.geometry
260 Emacs.geometry
261
262 Other possibilities for widget hierarchies might be
263
264 argv[0] frame pane Frame-NAME
265 ApplicationShell EmacsShell Paned EmacsFrame
266 or
267 argv[0] Frame-NAME pane Frame-NAME
268 ApplicationShell EmacsShell Paned EmacsFrame
269 or
270 argv[0] Frame-NAME pane emacsTextPane
271 ApplicationShell EmacsFrame Paned EmacsTextPane
272
273 With the current setup, the text-display-area is the part which is
274 an emacs "frame", since that's the only part managed by emacs proper
275 (the menubar and the parent of the menubar and all that sort of thing
276 are managed by lwlib.)
277
177c0ea7 278 The EmacsShell widget is simply a replacement for the Shell widget
07bf635f
RS
279 which is able to deal with using an externally-supplied window instead
280 of always creating its own. It is not actually emacs specific, and
281 should possibly have class "Shell" instead of "EmacsShell" to simplify
282 the resources.
283
284 */
285
07bf635f 286 /* Hairily merged geometry */
90022f5a
KS
287 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
288 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
177c0ea7 289
07bf635f 290 Widget wmshell = get_wm_shell ((Widget) ew);
38971c41 291 /* Each Emacs shell is now independent and top-level. */
177c0ea7 292
07bf635f 293 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
07bf635f 294
177c0ea7 295 /* We don't need this for the moment. The geometry is computed in
edaf359b
FP
296 xfns.c. */
297#if 0
07bf635f
RS
298 /* If the EmacsFrame doesn't have a geometry but the shell does,
299 treat that as the geometry of the frame. (Is this bogus?
300 I'm not sure.) */
301 if (ew->emacs_frame.geometry == 0)
c52e7aa6 302 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
07bf635f
RS
303
304 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
305 this bogus? I'm not sure.) */
306 if (!ew->emacs_frame.iconic)
c52e7aa6 307 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
177c0ea7
JB
308
309
07bf635f
RS
310 {
311 char *geom = 0;
c52e7aa6 312 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
07bf635f
RS
313 if (geom)
314 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
315 }
177c0ea7 316
07bf635f
RS
317 if (ew->emacs_frame.geometry)
318 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
319 &frame_x, &frame_y,
320 &frame_w, &frame_h);
177c0ea7 321
07bf635f
RS
322 if (first_frame_p)
323 {
324 /* If this is the first frame created:
325 ====================================
326
327 - Use the ApplicationShell's size/position, if specified.
328 (This is "Emacs.geometry", or the "-geometry" command line arg.)
329 - Else use the EmacsFrame's size/position.
330 (This is "*Frame-NAME.geometry")
331
332 - If the AppShell is iconic, the frame should be iconic.
333
334 AppShell comes first so that -geometry always applies to the first
335 frame created, even if there is an "every frame" entry in the
336 resource database.
337 */
338 if (app_flags & (XValue | YValue))
339 {
340 x = app_x; y = app_y;
341 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
342 }
343 else if (frame_flags & (XValue | YValue))
344 {
345 x = frame_x; y = frame_y;
346 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
347 }
348
349 if (app_flags & (WidthValue | HeightValue))
350 {
351 w = app_w; h = app_h;
352 flags |= (app_flags & (WidthValue | HeightValue));
353 }
354 else if (frame_flags & (WidthValue | HeightValue))
355 {
356 w = frame_w; h = frame_h;
357 flags |= (frame_flags & (WidthValue | HeightValue));
358 }
359
360 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
361 if (!ew->emacs_frame.iconic)
c52e7aa6 362 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
07bf635f
RS
363
364 first_frame_p = False;
365 }
366 else
367 {
368 /* If this is not the first frame created:
369 ========================================
370
371 - use the EmacsFrame's size/position if specified
372 - Otherwise, use the ApplicationShell's size, but not position.
373
374 So that means that one can specify the position of the first frame
375 with "Emacs.geometry" or `-geometry'; but can only specify the
376 position of subsequent frames with "*Frame-NAME.geometry".
377
378 AppShell comes second so that -geometry does not apply to subsequent
379 frames when there is an "every frame" entry in the resource db,
380 but does apply to the first frame.
381 */
382 if (frame_flags & (XValue | YValue))
383 {
384 x = frame_x; y = frame_y;
385 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
386 }
387
388 if (frame_flags & (WidthValue | HeightValue))
389 {
390 w = frame_w; h = frame_h;
391 flags |= (frame_flags & (WidthValue | HeightValue));
392 }
393 else if (app_flags & (WidthValue | HeightValue))
394 {
395 w = app_w;
396 h = app_h;
397 flags |= (app_flags & (WidthValue | HeightValue));
398 }
399 }
edaf359b 400#endif /* 0 */
07bf635f 401 {
90022f5a 402 struct frame *f = ew->emacs_frame.frame;
07bf635f 403 Dimension pixel_width, pixel_height;
07bf635f 404
f403d3c3
GM
405 /* Take into account the size of the scrollbar. Always use the
406 number of columns occupied by the scroll bar here otherwise we
407 might end up with a frame width that is not a multiple of the
408 frame's character width which is bad for vertically split
409 windows. */
90022f5a
KS
410 f->scroll_bar_actual_width
411 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
07bf635f 412
90022f5a 413 compute_fringe_widths (f, 0);
f403d3c3 414
de70f8b6
RS
415#if 0 /* This can run Lisp code, and it is dangerous to give
416 out the frame to Lisp code before it officially exists.
417 This is handled in Fx_create_frame so not needed here. */
90022f5a 418 change_frame_size (f, h, w, 1, 0, 0);
de70f8b6 419#endif
07bf635f
RS
420 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
421 ew->core.width = pixel_width;
422 ew->core.height = pixel_height;
423
6ae9a3f2 424#if 0 /* xfns.c takes care of this now. */
07bf635f
RS
425 /* If a position was specified, assign it to the shell widget.
426 (Else WM won't do anything with it.)
427 */
428 if (flags & (XValue | YValue))
429 {
430 /* the tricky things with the sign is to make sure that
431 -0 is printed -0. */
07bf635f
RS
432 sprintf (shell_position, "=%c%d%c%d",
433 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
434 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
e99a530f 435 XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
07bf635f
RS
436 }
437 else if (flags & (WidthValue | HeightValue))
438 {
07bf635f 439 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
e99a530f 440 XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
07bf635f
RS
441 }
442
443 /* If the geometry spec we're using has W/H components, mark the size
444 in the WM_SIZE_HINTS as user specified. */
445 if (flags & (WidthValue | HeightValue))
446 mark_shell_size_user_specified (wmshell);
447
448 /* Also assign the iconic status of the frame to the Shell, so that
449 the WM sees it. */
c52e7aa6 450 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
edaf359b 451#endif /* 0 */
07bf635f
RS
452 }
453}
454
07bf635f 455static void
ebd15611 456update_wm_hints (EmacsFrame ew)
07bf635f
RS
457{
458 Widget wmshell = get_wm_shell ((Widget)ew);
459 int cw;
460 int ch;
461 Dimension rounded_width;
462 Dimension rounded_height;
463 int char_width;
464 int char_height;
465 int base_width;
466 int base_height;
467 int min_rows = 0, min_cols = 0;
468
c052ead4
JD
469 /* This happens when the frame is just created. */
470 if (! wmshell) return;
471
cfcd12d6 472#if 0
07bf635f 473 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
cfcd12d6 474#endif
07bf635f
RS
475
476 pixel_to_char_size (ew, ew->core.width, ew->core.height,
477 &char_width, &char_height);
478 char_to_pixel_size (ew, char_width, char_height,
479 &rounded_width, &rounded_height);
177c0ea7 480 get_default_char_pixel_size (ew, &cw, &ch);
07bf635f
RS
481
482 base_width = (wmshell->core.width - ew->core.width
483 + (rounded_width - (char_width * cw)));
484 base_height = (wmshell->core.height - ew->core.height
485 + (rounded_height - (char_height * ch)));
486
487 /* This is kind of sleazy, but I can't see how else to tell it to
488 make it mark the WM_SIZE_HINTS size as user specified.
489 */
490/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
491
492 XtVaSetValues (wmshell,
cbec8c51
GM
493 XtNbaseWidth, (XtArgVal) base_width,
494 XtNbaseHeight, (XtArgVal) base_height,
177c0ea7 495 XtNwidthInc, (XtArgVal) cw,
cbec8c51
GM
496 XtNheightInc, (XtArgVal) ch,
497 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
498 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
c52e7aa6 499 NULL);
07bf635f
RS
500}
501
c052ead4
JD
502void
503widget_update_wm_size_hints (Widget widget)
504{
505 EmacsFrame ew = (EmacsFrame)widget;
506 update_wm_hints (ew);
507}
508
509
ccce6056
GM
510#if 0
511
07bf635f 512static void
1dae0f0a 513create_frame_gcs (EmacsFrame ew)
07bf635f 514{
7f18598b 515 struct frame *s = ew->emacs_frame.frame;
07bf635f 516
54e9e953 517 s->output_data.x->normal_gc
578c21e6 518 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
54e9e953 519 s->output_data.x->reverse_gc
578c21e6 520 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
54e9e953 521 s->output_data.x->cursor_gc
578c21e6 522 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
f403d3c3
GM
523 s->output_data.x->black_relief.gc = 0;
524 s->output_data.x->white_relief.gc = 0;
07bf635f
RS
525}
526
ccce6056
GM
527#endif /* 0 */
528
1ad2277b
RS
529static char setup_frame_cursor_bits[] =
530{
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
535};
536
07bf635f 537static void
ebd15611 538setup_frame_gcs (EmacsFrame ew)
07bf635f
RS
539{
540 XGCValues gc_values;
541 struct frame* s = ew->emacs_frame.frame;
542 Pixmap blank_stipple, blank_tile;
39d14c25
CY
543 unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
544 | GCStipple | GCTile);
545 Lisp_Object font;
546
547 XSETFONT (font, ew->emacs_frame.font);
548 font = Ffont_xlfd_name (font, Qnil);
549 if (STRINGP (font))
550 {
551 XFontStruct *xfont = XLoadQueryFont (FRAME_X_DISPLAY_INFO (s)->display,
42a5b22f 552 SSDATA (font));
39d14c25
CY
553 if (xfont)
554 {
555 gc_values.font = xfont->fid;
556 valuemask |= GCFont;
557 }
558 }
07bf635f 559
07bf635f
RS
560 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
561 XGetGCValues returns uninitialized data when we query the stipple
562 (instead of None or something sensible) and it makes things hard.
563
564 This should be fixed for real by not querying the GCs but instead having
565 some GC-based cache instead of the current face-based cache which doesn't
566 effectively cache all of the GC settings we need to use.
567 */
568
85e53327
KH
569 blank_stipple
570 = XCreateBitmapFromData (XtDisplay (ew),
571 RootWindowOfScreen (XtScreen (ew)),
572 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
573
574 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
575 never actually get used as a background tile!
576 */
85e53327 577 blank_tile
5e617bc2 578 = XCreatePixmapFromBitmapData (XtDisplay (ew),
85e53327
KH
579 RootWindowOfScreen (XtScreen (ew)),
580 setup_frame_cursor_bits, 2, 2,
578c21e6 581 0, 1, ew->core.depth);
07bf635f
RS
582
583 /* Normal video */
07bf635f
RS
584 gc_values.foreground = ew->emacs_frame.foreground_pixel;
585 gc_values.background = ew->core.background_pixel;
586 gc_values.graphics_exposures = False;
587 gc_values.stipple = blank_stipple;
588 gc_values.tile = blank_tile;
54e9e953 589 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
39d14c25 590 valuemask, &gc_values);
07bf635f
RS
591
592 /* Reverse video style. */
07bf635f
RS
593 gc_values.foreground = ew->core.background_pixel;
594 gc_values.background = ew->emacs_frame.foreground_pixel;
595 gc_values.graphics_exposures = False;
596 gc_values.stipple = blank_stipple;
597 gc_values.tile = blank_tile;
54e9e953 598 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
39d14c25 599 valuemask, &gc_values);
07bf635f
RS
600
601 /* Cursor has to have an empty stipple. */
07bf635f
RS
602 gc_values.foreground = ew->core.background_pixel;
603 gc_values.background = ew->emacs_frame.cursor_color;
604 gc_values.graphics_exposures = False;
605 gc_values.tile = blank_tile;
85e53327
KH
606 gc_values.stipple
607 = XCreateBitmapFromData (XtDisplay (ew),
608 RootWindowOfScreen (XtScreen (ew)),
609 setup_frame_cursor_bits, 16, 16);
54e9e953 610 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
39d14c25 611 valuemask, &gc_values);
07bf635f
RS
612}
613
614static void
ebd15611 615update_various_frame_slots (EmacsFrame ew)
07bf635f 616{
90022f5a
KS
617 struct frame *f = ew->emacs_frame.frame;
618 struct x_output *x = f->output_data.x;
619 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
620 FRAME_PIXEL_WIDTH (f) = ew->core.width;
621 f->internal_border_width = ew->emacs_frame.internal_border_width;
07bf635f
RS
622
623}
624
625static void
ebd15611 626update_from_various_frame_slots (EmacsFrame ew)
07bf635f 627{
90022f5a
KS
628 struct frame *f = ew->emacs_frame.frame;
629 struct x_output *x = f->output_data.x;
630 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
631 ew->core.width = FRAME_PIXEL_WIDTH (f);
ce593f6e 632 ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
90022f5a 633 ew->emacs_frame.internal_border_width = f->internal_border_width;
07bf635f 634 ew->emacs_frame.font = x->font;
ce593f6e 635 ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
07bf635f
RS
636 ew->emacs_frame.cursor_color = x->cursor_pixel;
637 ew->core.border_pixel = x->border_pixel;
638}
639
177c0ea7 640static void
ebd15611 641EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
07bf635f
RS
642{
643 EmacsFrame ew = (EmacsFrame)new;
644
645 if (!ew->emacs_frame.frame)
646 {
647 fprintf (stderr,
648 "can't create an emacs frame widget without a frame\n");
649 exit (1);
650 }
651
07bf635f 652 update_from_various_frame_slots (ew);
177c0ea7 653 set_frame_size (ew);
07bf635f
RS
654}
655
656
657static void
ebd15611 658EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
07bf635f
RS
659{
660 EmacsFrame ew = (EmacsFrame)widget;
661
486a103d
GM
662 /* This used to contain SubstructureRedirectMask, but this turns out
663 to be a problem with XIM on Solaris, and events from that mask
2fce2bb4 664 don't seem to be used. Let's check that. */
486a103d
GM
665 attrs->event_mask = (STANDARD_EVENT_SET
666 | PropertyChangeMask
667 | SubstructureNotifyMask);
07bf635f
RS
668 *mask |= CWEventMask;
669 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
670 attrs);
177c0ea7 671 update_wm_hints (ew);
07bf635f
RS
672}
673
07bf635f 674static void
ebd15611 675EmacsFrameDestroy (Widget widget)
07bf635f
RS
676{
677 EmacsFrame ew = (EmacsFrame) widget;
678 struct frame* s = ew->emacs_frame.frame;
679
680 if (! s) abort ();
54e9e953 681 if (! s->output_data.x) abort ();
07bf635f 682
49fe12a9 683 BLOCK_INPUT;
0dea0fed 684 x_free_gcs (s);
f403d3c3
GM
685 if (s->output_data.x->white_relief.gc)
686 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
687 if (s->output_data.x->black_relief.gc)
688 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
49fe12a9 689 UNBLOCK_INPUT;
07bf635f
RS
690}
691
4475bec4 692static void
ebd15611 693EmacsFrameResize (Widget widget)
07bf635f
RS
694{
695 EmacsFrame ew = (EmacsFrame)widget;
696 struct frame *f = ew->emacs_frame.frame;
697 int columns;
698 int rows;
699
700 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
2b653806 701 change_frame_size (f, rows, columns, 0, 1, 0);
177c0ea7 702 update_wm_hints (ew);
07bf635f 703 update_various_frame_slots (ew);
49feb47d
RS
704
705 cancel_mouse_face (f);
07bf635f
RS
706}
707
708static Boolean
ebd15611 709EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
07bf635f
RS
710{
711 EmacsFrame cur = (EmacsFrame)cur_widget;
712 EmacsFrame new = (EmacsFrame)new_widget;
713
714 Boolean needs_a_refresh = False;
715 Boolean has_to_recompute_size;
716 Boolean has_to_recompute_gcs;
717 Boolean has_to_update_hints;
718
719 int char_width, char_height;
720 Dimension pixel_width;
721 Dimension pixel_height;
177c0ea7 722
5c646d5a 723 /* AFAIK, this function is never called. -- Jan D, Oct 2009. */
07bf635f
RS
724 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
725 || (cur->emacs_frame.foreground_pixel
726 != new->emacs_frame.foreground_pixel)
727 || (cur->core.background_pixel
728 != new->core.background_pixel)
729 );
177c0ea7 730
07bf635f
RS
731 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
732 && cur->core.width == new->core.width
733 && cur->core.height == new->core.height);
734
735 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
736
737 if (has_to_recompute_gcs)
738 {
739 setup_frame_gcs (new);
740 needs_a_refresh = True;
741 }
177c0ea7 742
07bf635f
RS
743 if (has_to_recompute_size)
744 {
745 pixel_width = new->core.width;
746 pixel_height = new->core.height;
747 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
748 &char_height);
749 char_to_pixel_size (new, char_width, char_height, &pixel_width,
750 &pixel_height);
751 new->core.width = pixel_width;
752 new->core.height = pixel_height;
753
754 change_frame_size (new->emacs_frame.frame, char_height, char_width,
2b653806 755 1, 0, 0);
07bf635f
RS
756 needs_a_refresh = True;
757 }
758
759 if (has_to_update_hints)
760 update_wm_hints (new);
761
762 update_various_frame_slots (new);
763
764 /* #### This doesn't work, I haven't been able to find ANY kludge that
765 will let (x-create-frame '((iconic . t))) work. It seems that changes
766 to wm_shell's iconic slot have no effect after it has been realized,
2dd5c7f7 767 and calling XIconifyWindow doesn't work either (even though the window
07bf635f 768 has been created.) Perhaps there is some property we could smash
ac26ca64 769 directly, but I'm sick of this for now.
07bf635f
RS
770 */
771 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
772 {
773 Widget wmshell = get_wm_shell ((Widget) cur);
cbec8c51
GM
774 XtVaSetValues (wmshell, XtNiconic,
775 (XtArgVal) new->emacs_frame.iconic, NULL);
07bf635f
RS
776 }
777
778 return needs_a_refresh;
779}
780
781static XtGeometryResult
ebd15611 782EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
07bf635f
RS
783{
784 EmacsFrame ew = (EmacsFrame)widget;
785
786 int mask = request->request_mode;
787 Dimension ok_width, ok_height;
788
789 if (mask & (CWWidth | CWHeight))
790 {
791 round_size_to_char (ew,
792 (mask & CWWidth) ? request->width : ew->core.width,
793 ((mask & CWHeight) ? request->height
794 : ew->core.height),
795 &ok_width, &ok_height);
796 if ((mask & CWWidth) && (ok_width != request->width))
797 {
798 result->request_mode |= CWWidth;
799 result->width = ok_width;
800 }
801 if ((mask & CWHeight) && (ok_height != request->height))
802 {
803 result->request_mode |= CWHeight;
804 result->height = ok_height;
805 }
806 }
807 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
808}
809
e4769531 810/* Special entry points */
07bf635f 811void
ebd15611 812EmacsFrameSetCharSize (Widget widget, int columns, int rows)
07bf635f
RS
813{
814 EmacsFrame ew = (EmacsFrame) widget;
982a94d9 815 struct frame *f = ew->emacs_frame.frame;
177c0ea7 816
5c646d5a 817 x_set_window_size (f, 0, columns, rows);
07bf635f 818}
f403d3c3 819
d793b105 820\f
dfcf069d 821void
ebd15611 822widget_store_internal_border (Widget widget)
d793b105
RS
823{
824 EmacsFrame ew = (EmacsFrame) widget;
825 FRAME_PTR f = ew->emacs_frame.frame;
826
90022f5a 827 ew->emacs_frame.internal_border_width = f->internal_border_width;
d793b105 828}