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