Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / src / widget.c
CommitLineData
07bf635f 1/* The emacs frame widget.
73b0cd50 2 Copyright (C) 1992-1993, 2000-2011 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);
81void EmacsFrameResize (Widget widget);
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)))
89#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
90
91static XtResource resources[] = {
92 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
93 offset (geometry), XtRString, (XtPointer) 0},
94 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
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},
39d14c25 108 {XtNfont, XtCFont, XtRFontStruct, sizeof(struct font *),
07bf635f
RS
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"},
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
140EmacsFrameClassRec emacsFrameClassRec = {
141 { /* core fields */
142 /* superclass */ &widgetClassRec,
143 /* class_name */ "EmacsFrame",
144 /* widget_size */ sizeof(EmacsFrameRec),
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,
154 /* resource_count */ XtNumber(resources),
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
345a94f9
RS
227mark_shell_size_user_specified (wmshell)
228 Widget wmshell;
07bf635f
RS
229{
230 if (! XtIsWMShell (wmshell)) abort ();
231 /* This is kind of sleazy, but I can't see how else to tell it to make it
232 mark the WM_SIZE_HINTS size as user specified when appropriate. */
233 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
234}
235
ccce6056
GM
236#endif
237
07bf635f
RS
238
239/* Can't have static frame locals because of some broken compilers.
240 Normally, initializing a variable like this doesn't work in emacs,
241 but it's ok in this file because it must come after lastfile (and
242 thus have its data not go into text space) because Xt needs to
243 write to initialized data objects too.
244 */
ccce6056 245#if 0
07bf635f 246static Boolean first_frame_p = True;
ccce6056 247#endif
07bf635f
RS
248
249static void
ebd15611 250set_frame_size (EmacsFrame ew)
07bf635f
RS
251{
252 /* The widget hierarchy is
253
254 argv[0] emacsShell pane Frame-NAME
255 ApplicationShell EmacsShell Paned EmacsFrame
256
257 We accept geometry specs in this order:
258
259 *Frame-NAME.geometry
260 *EmacsFrame.geometry
261 Emacs.geometry
262
263 Other possibilities for widget hierarchies might be
264
265 argv[0] frame pane Frame-NAME
266 ApplicationShell EmacsShell Paned EmacsFrame
267 or
268 argv[0] Frame-NAME pane Frame-NAME
269 ApplicationShell EmacsShell Paned EmacsFrame
270 or
271 argv[0] Frame-NAME pane emacsTextPane
272 ApplicationShell EmacsFrame Paned EmacsTextPane
273
274 With the current setup, the text-display-area is the part which is
275 an emacs "frame", since that's the only part managed by emacs proper
276 (the menubar and the parent of the menubar and all that sort of thing
277 are managed by lwlib.)
278
177c0ea7 279 The EmacsShell widget is simply a replacement for the Shell widget
07bf635f
RS
280 which is able to deal with using an externally-supplied window instead
281 of always creating its own. It is not actually emacs specific, and
282 should possibly have class "Shell" instead of "EmacsShell" to simplify
283 the resources.
284
285 */
286
07bf635f 287 /* Hairily merged geometry */
90022f5a
KS
288 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
289 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
177c0ea7 290
07bf635f 291 Widget wmshell = get_wm_shell ((Widget) ew);
38971c41 292 /* Each Emacs shell is now independent and top-level. */
177c0ea7 293
07bf635f 294 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
07bf635f 295
177c0ea7 296 /* We don't need this for the moment. The geometry is computed in
edaf359b
FP
297 xfns.c. */
298#if 0
07bf635f
RS
299 /* If the EmacsFrame doesn't have a geometry but the shell does,
300 treat that as the geometry of the frame. (Is this bogus?
301 I'm not sure.) */
302 if (ew->emacs_frame.geometry == 0)
c52e7aa6 303 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
07bf635f
RS
304
305 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
306 this bogus? I'm not sure.) */
307 if (!ew->emacs_frame.iconic)
c52e7aa6 308 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
177c0ea7
JB
309
310
07bf635f
RS
311 {
312 char *geom = 0;
c52e7aa6 313 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
07bf635f
RS
314 if (geom)
315 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
316 }
177c0ea7 317
07bf635f
RS
318 if (ew->emacs_frame.geometry)
319 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
320 &frame_x, &frame_y,
321 &frame_w, &frame_h);
177c0ea7 322
07bf635f
RS
323 if (first_frame_p)
324 {
325 /* If this is the first frame created:
326 ====================================
327
328 - Use the ApplicationShell's size/position, if specified.
329 (This is "Emacs.geometry", or the "-geometry" command line arg.)
330 - Else use the EmacsFrame's size/position.
331 (This is "*Frame-NAME.geometry")
332
333 - If the AppShell is iconic, the frame should be iconic.
334
335 AppShell comes first so that -geometry always applies to the first
336 frame created, even if there is an "every frame" entry in the
337 resource database.
338 */
339 if (app_flags & (XValue | YValue))
340 {
341 x = app_x; y = app_y;
342 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
343 }
344 else if (frame_flags & (XValue | YValue))
345 {
346 x = frame_x; y = frame_y;
347 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
348 }
349
350 if (app_flags & (WidthValue | HeightValue))
351 {
352 w = app_w; h = app_h;
353 flags |= (app_flags & (WidthValue | HeightValue));
354 }
355 else if (frame_flags & (WidthValue | HeightValue))
356 {
357 w = frame_w; h = frame_h;
358 flags |= (frame_flags & (WidthValue | HeightValue));
359 }
360
361 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
362 if (!ew->emacs_frame.iconic)
c52e7aa6 363 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
07bf635f
RS
364
365 first_frame_p = False;
366 }
367 else
368 {
369 /* If this is not the first frame created:
370 ========================================
371
372 - use the EmacsFrame's size/position if specified
373 - Otherwise, use the ApplicationShell's size, but not position.
374
375 So that means that one can specify the position of the first frame
376 with "Emacs.geometry" or `-geometry'; but can only specify the
377 position of subsequent frames with "*Frame-NAME.geometry".
378
379 AppShell comes second so that -geometry does not apply to subsequent
380 frames when there is an "every frame" entry in the resource db,
381 but does apply to the first frame.
382 */
383 if (frame_flags & (XValue | YValue))
384 {
385 x = frame_x; y = frame_y;
386 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
387 }
388
389 if (frame_flags & (WidthValue | HeightValue))
390 {
391 w = frame_w; h = frame_h;
392 flags |= (frame_flags & (WidthValue | HeightValue));
393 }
394 else if (app_flags & (WidthValue | HeightValue))
395 {
396 w = app_w;
397 h = app_h;
398 flags |= (app_flags & (WidthValue | HeightValue));
399 }
400 }
edaf359b 401#endif /* 0 */
07bf635f 402 {
90022f5a 403 struct frame *f = ew->emacs_frame.frame;
07bf635f 404 Dimension pixel_width, pixel_height;
07bf635f 405
f403d3c3
GM
406 /* Take into account the size of the scrollbar. Always use the
407 number of columns occupied by the scroll bar here otherwise we
408 might end up with a frame width that is not a multiple of the
409 frame's character width which is bad for vertically split
410 windows. */
90022f5a
KS
411 f->scroll_bar_actual_width
412 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
07bf635f 413
90022f5a 414 compute_fringe_widths (f, 0);
f403d3c3 415
de70f8b6
RS
416#if 0 /* This can run Lisp code, and it is dangerous to give
417 out the frame to Lisp code before it officially exists.
418 This is handled in Fx_create_frame so not needed here. */
90022f5a 419 change_frame_size (f, h, w, 1, 0, 0);
de70f8b6 420#endif
07bf635f
RS
421 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
422 ew->core.width = pixel_width;
423 ew->core.height = pixel_height;
424
6ae9a3f2 425#if 0 /* xfns.c takes care of this now. */
07bf635f
RS
426 /* If a position was specified, assign it to the shell widget.
427 (Else WM won't do anything with it.)
428 */
429 if (flags & (XValue | YValue))
430 {
431 /* the tricky things with the sign is to make sure that
432 -0 is printed -0. */
433 int len;
434 char *tem;
435 sprintf (shell_position, "=%c%d%c%d",
436 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
437 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
438 len = strlen (shell_position) + 1;
439 tem = (char *) xmalloc (len);
440 strncpy (tem, shell_position, len);
c52e7aa6 441 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
07bf635f
RS
442 }
443 else if (flags & (WidthValue | HeightValue))
444 {
445 int len;
446 char *tem;
447 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
448 len = strlen (shell_position) + 1;
449 tem = (char *) xmalloc (len);
450 strncpy (tem, shell_position, len);
c52e7aa6 451 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
07bf635f
RS
452 }
453
454 /* If the geometry spec we're using has W/H components, mark the size
455 in the WM_SIZE_HINTS as user specified. */
456 if (flags & (WidthValue | HeightValue))
457 mark_shell_size_user_specified (wmshell);
458
459 /* Also assign the iconic status of the frame to the Shell, so that
460 the WM sees it. */
c52e7aa6 461 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
edaf359b 462#endif /* 0 */
07bf635f
RS
463 }
464}
465
cfcd12d6
KH
466/* Nonzero tells update_wm_hints not to do anything
467 (the caller should call update_wm_hints explicitly later.) */
468int update_hints_inhibit;
07bf635f
RS
469
470static void
ebd15611 471update_wm_hints (EmacsFrame ew)
07bf635f
RS
472{
473 Widget wmshell = get_wm_shell ((Widget)ew);
474 int cw;
475 int ch;
476 Dimension rounded_width;
477 Dimension rounded_height;
478 int char_width;
479 int char_height;
480 int base_width;
481 int base_height;
482 int min_rows = 0, min_cols = 0;
483
cfcd12d6
KH
484 if (update_hints_inhibit)
485 return;
486
487#if 0
07bf635f 488 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
cfcd12d6 489#endif
07bf635f
RS
490
491 pixel_to_char_size (ew, ew->core.width, ew->core.height,
492 &char_width, &char_height);
493 char_to_pixel_size (ew, char_width, char_height,
494 &rounded_width, &rounded_height);
177c0ea7 495 get_default_char_pixel_size (ew, &cw, &ch);
07bf635f
RS
496
497 base_width = (wmshell->core.width - ew->core.width
498 + (rounded_width - (char_width * cw)));
499 base_height = (wmshell->core.height - ew->core.height
500 + (rounded_height - (char_height * ch)));
501
502 /* This is kind of sleazy, but I can't see how else to tell it to
503 make it mark the WM_SIZE_HINTS size as user specified.
504 */
505/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
506
507 XtVaSetValues (wmshell,
cbec8c51
GM
508 XtNbaseWidth, (XtArgVal) base_width,
509 XtNbaseHeight, (XtArgVal) base_height,
177c0ea7 510 XtNwidthInc, (XtArgVal) cw,
cbec8c51
GM
511 XtNheightInc, (XtArgVal) ch,
512 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
513 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
c52e7aa6 514 NULL);
07bf635f
RS
515}
516
ccce6056
GM
517#if 0
518
07bf635f 519static void
345a94f9
RS
520create_frame_gcs (ew)
521 EmacsFrame ew;
07bf635f 522{
7f18598b 523 struct frame *s = ew->emacs_frame.frame;
07bf635f 524
54e9e953 525 s->output_data.x->normal_gc
85e53327
KH
526 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
527 (unsigned long)0, (XGCValues *)0);
54e9e953 528 s->output_data.x->reverse_gc
85e53327
KH
529 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
530 (unsigned long)0, (XGCValues *)0);
54e9e953 531 s->output_data.x->cursor_gc
85e53327
KH
532 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
533 (unsigned long)0, (XGCValues *)0);
f403d3c3
GM
534 s->output_data.x->black_relief.gc = 0;
535 s->output_data.x->white_relief.gc = 0;
07bf635f
RS
536}
537
ccce6056
GM
538#endif /* 0 */
539
1ad2277b
RS
540static char setup_frame_cursor_bits[] =
541{
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
546};
547
07bf635f 548static void
ebd15611 549setup_frame_gcs (EmacsFrame ew)
07bf635f
RS
550{
551 XGCValues gc_values;
552 struct frame* s = ew->emacs_frame.frame;
553 Pixmap blank_stipple, blank_tile;
39d14c25
CY
554 unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
555 | GCStipple | GCTile);
556 Lisp_Object font;
557
558 XSETFONT (font, ew->emacs_frame.font);
559 font = Ffont_xlfd_name (font, Qnil);
560 if (STRINGP (font))
561 {
562 XFontStruct *xfont = XLoadQueryFont (FRAME_X_DISPLAY_INFO (s)->display,
563 SDATA (font));
564 if (xfont)
565 {
566 gc_values.font = xfont->fid;
567 valuemask |= GCFont;
568 }
569 }
07bf635f 570
07bf635f
RS
571 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
572 XGetGCValues returns uninitialized data when we query the stipple
573 (instead of None or something sensible) and it makes things hard.
574
575 This should be fixed for real by not querying the GCs but instead having
576 some GC-based cache instead of the current face-based cache which doesn't
577 effectively cache all of the GC settings we need to use.
578 */
579
85e53327
KH
580 blank_stipple
581 = XCreateBitmapFromData (XtDisplay (ew),
582 RootWindowOfScreen (XtScreen (ew)),
583 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
584
585 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
586 never actually get used as a background tile!
587 */
85e53327
KH
588 blank_tile
589 = XCreatePixmapFromBitmapData (XtDisplay(ew),
590 RootWindowOfScreen (XtScreen (ew)),
591 setup_frame_cursor_bits, 2, 2,
592 (unsigned long)0, (unsigned long)1,
593 ew->core.depth);
07bf635f
RS
594
595 /* Normal video */
07bf635f
RS
596 gc_values.foreground = ew->emacs_frame.foreground_pixel;
597 gc_values.background = ew->core.background_pixel;
598 gc_values.graphics_exposures = False;
599 gc_values.stipple = blank_stipple;
600 gc_values.tile = blank_tile;
54e9e953 601 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
39d14c25 602 valuemask, &gc_values);
07bf635f
RS
603
604 /* Reverse video style. */
07bf635f
RS
605 gc_values.foreground = ew->core.background_pixel;
606 gc_values.background = ew->emacs_frame.foreground_pixel;
607 gc_values.graphics_exposures = False;
608 gc_values.stipple = blank_stipple;
609 gc_values.tile = blank_tile;
54e9e953 610 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
39d14c25 611 valuemask, &gc_values);
07bf635f
RS
612
613 /* Cursor has to have an empty stipple. */
07bf635f
RS
614 gc_values.foreground = ew->core.background_pixel;
615 gc_values.background = ew->emacs_frame.cursor_color;
616 gc_values.graphics_exposures = False;
617 gc_values.tile = blank_tile;
85e53327
KH
618 gc_values.stipple
619 = XCreateBitmapFromData (XtDisplay (ew),
620 RootWindowOfScreen (XtScreen (ew)),
621 setup_frame_cursor_bits, 16, 16);
54e9e953 622 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
39d14c25 623 valuemask, &gc_values);
07bf635f
RS
624}
625
626static void
ebd15611 627update_various_frame_slots (EmacsFrame ew)
07bf635f 628{
90022f5a
KS
629 struct frame *f = ew->emacs_frame.frame;
630 struct x_output *x = f->output_data.x;
631 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
632 FRAME_PIXEL_WIDTH (f) = ew->core.width;
633 f->internal_border_width = ew->emacs_frame.internal_border_width;
07bf635f
RS
634
635}
636
637static void
ebd15611 638update_from_various_frame_slots (EmacsFrame ew)
07bf635f 639{
90022f5a
KS
640 struct frame *f = ew->emacs_frame.frame;
641 struct x_output *x = f->output_data.x;
642 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
643 ew->core.width = FRAME_PIXEL_WIDTH (f);
ce593f6e 644 ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
90022f5a 645 ew->emacs_frame.internal_border_width = f->internal_border_width;
07bf635f 646 ew->emacs_frame.font = x->font;
ce593f6e 647 ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
07bf635f
RS
648 ew->emacs_frame.cursor_color = x->cursor_pixel;
649 ew->core.border_pixel = x->border_pixel;
650}
651
177c0ea7 652static void
ebd15611 653EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
07bf635f
RS
654{
655 EmacsFrame ew = (EmacsFrame)new;
656
657 if (!ew->emacs_frame.frame)
658 {
659 fprintf (stderr,
660 "can't create an emacs frame widget without a frame\n");
661 exit (1);
662 }
663
07bf635f 664 update_from_various_frame_slots (ew);
177c0ea7 665 set_frame_size (ew);
07bf635f
RS
666}
667
668
669static void
ebd15611 670EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
07bf635f
RS
671{
672 EmacsFrame ew = (EmacsFrame)widget;
673
486a103d
GM
674 /* This used to contain SubstructureRedirectMask, but this turns out
675 to be a problem with XIM on Solaris, and events from that mask
2fce2bb4 676 don't seem to be used. Let's check that. */
486a103d
GM
677 attrs->event_mask = (STANDARD_EVENT_SET
678 | PropertyChangeMask
679 | SubstructureNotifyMask);
07bf635f
RS
680 *mask |= CWEventMask;
681 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
682 attrs);
177c0ea7 683 update_wm_hints (ew);
07bf635f
RS
684}
685
ebd15611 686extern void free_frame_faces (struct frame *);
07bf635f
RS
687
688static void
ebd15611 689EmacsFrameDestroy (Widget widget)
07bf635f
RS
690{
691 EmacsFrame ew = (EmacsFrame) widget;
692 struct frame* s = ew->emacs_frame.frame;
693
694 if (! s) abort ();
54e9e953 695 if (! s->output_data.x) abort ();
07bf635f 696
49fe12a9 697 BLOCK_INPUT;
0dea0fed 698 x_free_gcs (s);
f403d3c3
GM
699 if (s->output_data.x->white_relief.gc)
700 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
701 if (s->output_data.x->black_relief.gc)
702 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
49fe12a9 703 UNBLOCK_INPUT;
07bf635f
RS
704}
705
706void
ebd15611 707EmacsFrameResize (Widget widget)
07bf635f
RS
708{
709 EmacsFrame ew = (EmacsFrame)widget;
710 struct frame *f = ew->emacs_frame.frame;
711 int columns;
712 int rows;
713
714 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
2b653806 715 change_frame_size (f, rows, columns, 0, 1, 0);
177c0ea7 716 update_wm_hints (ew);
07bf635f 717 update_various_frame_slots (ew);
49feb47d
RS
718
719 cancel_mouse_face (f);
07bf635f
RS
720}
721
722static Boolean
ebd15611 723EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
07bf635f
RS
724{
725 EmacsFrame cur = (EmacsFrame)cur_widget;
726 EmacsFrame new = (EmacsFrame)new_widget;
727
728 Boolean needs_a_refresh = False;
729 Boolean has_to_recompute_size;
730 Boolean has_to_recompute_gcs;
731 Boolean has_to_update_hints;
732
733 int char_width, char_height;
734 Dimension pixel_width;
735 Dimension pixel_height;
177c0ea7 736
5c646d5a 737 /* AFAIK, this function is never called. -- Jan D, Oct 2009. */
07bf635f
RS
738 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
739 || (cur->emacs_frame.foreground_pixel
740 != new->emacs_frame.foreground_pixel)
741 || (cur->core.background_pixel
742 != new->core.background_pixel)
743 );
177c0ea7 744
07bf635f
RS
745 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
746 && cur->core.width == new->core.width
747 && cur->core.height == new->core.height);
748
749 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
750
751 if (has_to_recompute_gcs)
752 {
753 setup_frame_gcs (new);
754 needs_a_refresh = True;
755 }
177c0ea7 756
07bf635f
RS
757 if (has_to_recompute_size)
758 {
759 pixel_width = new->core.width;
760 pixel_height = new->core.height;
761 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
762 &char_height);
763 char_to_pixel_size (new, char_width, char_height, &pixel_width,
764 &pixel_height);
765 new->core.width = pixel_width;
766 new->core.height = pixel_height;
767
768 change_frame_size (new->emacs_frame.frame, char_height, char_width,
2b653806 769 1, 0, 0);
07bf635f
RS
770 needs_a_refresh = True;
771 }
772
773 if (has_to_update_hints)
774 update_wm_hints (new);
775
776 update_various_frame_slots (new);
777
778 /* #### This doesn't work, I haven't been able to find ANY kludge that
779 will let (x-create-frame '((iconic . t))) work. It seems that changes
780 to wm_shell's iconic slot have no effect after it has been realized,
2dd5c7f7 781 and calling XIconifyWindow doesn't work either (even though the window
07bf635f 782 has been created.) Perhaps there is some property we could smash
ac26ca64 783 directly, but I'm sick of this for now.
07bf635f
RS
784 */
785 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
786 {
787 Widget wmshell = get_wm_shell ((Widget) cur);
cbec8c51
GM
788 XtVaSetValues (wmshell, XtNiconic,
789 (XtArgVal) new->emacs_frame.iconic, NULL);
07bf635f
RS
790 }
791
792 return needs_a_refresh;
793}
794
795static XtGeometryResult
ebd15611 796EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
07bf635f
RS
797{
798 EmacsFrame ew = (EmacsFrame)widget;
799
800 int mask = request->request_mode;
801 Dimension ok_width, ok_height;
802
803 if (mask & (CWWidth | CWHeight))
804 {
805 round_size_to_char (ew,
806 (mask & CWWidth) ? request->width : ew->core.width,
807 ((mask & CWHeight) ? request->height
808 : ew->core.height),
809 &ok_width, &ok_height);
810 if ((mask & CWWidth) && (ok_width != request->width))
811 {
812 result->request_mode |= CWWidth;
813 result->width = ok_width;
814 }
815 if ((mask & CWHeight) && (ok_height != request->height))
816 {
817 result->request_mode |= CWHeight;
818 result->height = ok_height;
819 }
820 }
821 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
822}
823
07bf635f
RS
824/* Special entrypoints */
825void
ebd15611 826EmacsFrameSetCharSize (Widget widget, int columns, int rows)
07bf635f
RS
827{
828 EmacsFrame ew = (EmacsFrame) widget;
982a94d9 829 struct frame *f = ew->emacs_frame.frame;
177c0ea7 830
5c646d5a 831 x_set_window_size (f, 0, columns, rows);
07bf635f 832}
f403d3c3 833
d793b105 834\f
dfcf069d 835void
ebd15611 836widget_store_internal_border (Widget widget)
d793b105
RS
837{
838 EmacsFrame ew = (EmacsFrame) widget;
839 FRAME_PTR f = ew->emacs_frame.frame;
840
90022f5a 841 ew->emacs_frame.internal_border_width = f->internal_border_width;
d793b105 842}
ab5796a9 843