(x_set_font): Don't call face-set-after-frame-default
[bpt/emacs.git] / src / widget.c
CommitLineData
07bf635f
RS
1/* The emacs frame widget.
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
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
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
07bf635f
RS
20
21/* Emacs 19 face widget ported by Fred Pierresteguy */
22
ac26ca64
KH
23/* This file has been censored by the Communications Decency Act.
24 That law was passed under the guise of a ban on pornography, but
25 it bans far more than that. This file did not contain pornography,
26 but it was censored nonetheless.
27
28 For information on US government censorship of the Internet, and
29 what you can do to bring back freedom of the press, see the web
30 site http://www.vtw.org/
31 */
32
9e65ad77 33#include <config.h>
565620a5 34#include <stdio.h>
07bf635f
RS
35#include "lisp.h"
36#include "xterm.h"
37
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
RS
52
53#define max(a, b) ((a) > (b) ? (a) : (b))
54
55/* This sucks: this is the first default that x-faces.el tries. This won't
56 be used unless neither the "Emacs.EmacsFrame" resource nor the
57 "Emacs.EmacsFrame" resource is set; the frame
58 may have the wrong default size if this font doesn't exist, but some other
59 font that x-faces.el does. The workaround is to specify some font in the
60 resource database; I don't know a solution other than duplicating the font-
61 searching code from x-faces.el in this file.
62
63 This also means that if "Emacs.EmacsFrame" is specified as a non-
64 existent font, then Xt is going to substitute "XtDefaultFont" for it,
65 which is a different size than this one. The solution for this is to
66 make x-faces.el try to use XtDefaultFont. The problem with that is that
67 XtDefaultFont is almost certainly variable-width.
68
69 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
70 */
71#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
72
73
01492d1b
RS
74static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
75static void EmacsFrameDestroy (/* Widget */);
76static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
77void EmacsFrameResize (/* Widget widget */);
78static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
79 ArgList, Cardinal * */);
80static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
81 XtWidgetGeometry* */);
07bf635f
RS
82
83
84#undef XtOffset
85#define XtOffset(p_type,field) \
86 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
87#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
88
89static XtResource resources[] = {
90 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
91 offset (geometry), XtRString, (XtPointer) 0},
92 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
93 offset (iconic), XtRImmediate, (XtPointer) False},
94
95 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
96 offset (frame), XtRImmediate, 0},
97
98 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
99 offset (minibuffer), XtRImmediate, (XtPointer)0},
100 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
101 offset (unsplittable), XtRImmediate, (XtPointer)0},
102 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
103 offset (internal_border_width), XtRImmediate, (XtPointer)4},
104 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
105 offset (interline), XtRImmediate, (XtPointer)0},
106 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
107 offset(font),XtRString, DEFAULT_FACE_FONT},
108 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
109 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
110 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
111 offset(cursor_color), XtRString, "XtDefaultForeground"},
112 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
113 offset (bar_cursor), XtRImmediate, (XtPointer)0},
114 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
115 offset (visual_bell), XtRImmediate, (XtPointer)0},
116 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
117 offset (bell_volume), XtRImmediate, (XtPointer)0},
118};
119
120#undef offset
121
122/*
123static XtActionsRec
124emacsFrameActionsTable [] = {
125 {"keypress", key_press},
126 {"focus_in", emacs_frame_focus_handler},
127 {"focus_out", emacs_frame_focus_handler},
128};
129
130static char
131emacsFrameTranslations [] = "\
132<KeyPress>: keypress()\n\
133<FocusIn>: focus_in()\n\
134<FocusOut>: focus_out()\n\
135";
136*/
137
138EmacsFrameClassRec emacsFrameClassRec = {
139 { /* core fields */
140 /* superclass */ &widgetClassRec,
141 /* class_name */ "EmacsFrame",
142 /* widget_size */ sizeof(EmacsFrameRec),
143 /* class_initialize */ 0,
144 /* class_part_initialize */ 0,
145 /* class_inited */ FALSE,
146 /* initialize */ EmacsFrameInitialize,
147 /* initialize_hook */ 0,
148 /* realize */ EmacsFrameRealize,
149 /* actions */ 0, /*emacsFrameActionsTable*/
150 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
151 /* resources */ resources,
152 /* resource_count */ XtNumber(resources),
153 /* xrm_class */ NULLQUARK,
154 /* compress_motion */ TRUE,
155 /* compress_exposure */ TRUE,
156 /* compress_enterleave */ TRUE,
157 /* visible_interest */ FALSE,
158 /* destroy */ EmacsFrameDestroy,
159 /* resize */ EmacsFrameResize,
160 /* expose */ XtInheritExpose,
161 /* set_values */ EmacsFrameSetValues,
162 /* set_values_hook */ 0,
163 /* set_values_almost */ XtInheritSetValuesAlmost,
164 /* get_values_hook */ 0,
165 /* accept_focus */ XtInheritAcceptFocus,
166 /* version */ XtVersion,
167 /* callback_private */ 0,
168 /* tm_table */ 0, /*emacsFrameTranslations*/
169 /* query_geometry */ EmacsFrameQueryGeometry,
170 /* display_accelerator */ XtInheritDisplayAccelerator,
171 /* extension */ 0
172 }
173};
174
175WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
176
177static void
01492d1b
RS
178get_default_char_pixel_size (ew, pixel_width, pixel_height)
179 EmacsFrame ew;
180 int* pixel_width;
181 int* pixel_height;
07bf635f 182{
07bf635f 183 struct frame* f = ew->emacs_frame.frame;
54e9e953
KH
184 *pixel_width = FONT_WIDTH (f->output_data.x->font);
185 *pixel_height = f->output_data.x->line_height;
07bf635f
RS
186}
187
188static void
01492d1b
RS
189pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
190 EmacsFrame ew;
191 Dimension pixel_width;
192 Dimension pixel_height;
193 int* char_width;
194 int* char_height;
07bf635f
RS
195{
196 struct frame* f = ew->emacs_frame.frame;
f8eeed5b
RS
197 *char_width = PIXEL_TO_CHAR_WIDTH (f, (int) pixel_width);
198 *char_height = PIXEL_TO_CHAR_HEIGHT (f, (int) pixel_height);
07bf635f
RS
199}
200
201static void
345a94f9
RS
202char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
203 EmacsFrame ew;
204 int char_width;
205 int char_height;
206 Dimension* pixel_width;
207 Dimension* pixel_height;
07bf635f
RS
208{
209 struct frame* f = ew->emacs_frame.frame;
210 *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
211 *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
212}
213
214static void
345a94f9
RS
215round_size_to_char (ew, in_width, in_height, out_width, out_height)
216 EmacsFrame ew;
217 Dimension in_width;
218 Dimension in_height;
219 Dimension* out_width;
220 Dimension* out_height;
07bf635f
RS
221{
222 int char_width;
223 int char_height;
224 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
225 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
226}
227
228static Widget
345a94f9
RS
229get_wm_shell (w)
230 Widget w;
07bf635f
RS
231{
232 Widget wmshell;
233
234 for (wmshell = XtParent (w);
235 wmshell && !XtIsWMShell (wmshell);
236 wmshell = XtParent (wmshell));
237
238 return wmshell;
239}
240
241static void
345a94f9
RS
242mark_shell_size_user_specified (wmshell)
243 Widget wmshell;
07bf635f
RS
244{
245 if (! XtIsWMShell (wmshell)) abort ();
246 /* This is kind of sleazy, but I can't see how else to tell it to make it
247 mark the WM_SIZE_HINTS size as user specified when appropriate. */
248 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
249}
250
251
252/* Can't have static frame locals because of some broken compilers.
253 Normally, initializing a variable like this doesn't work in emacs,
254 but it's ok in this file because it must come after lastfile (and
255 thus have its data not go into text space) because Xt needs to
256 write to initialized data objects too.
257 */
258static Boolean first_frame_p = True;
259
260static void
345a94f9
RS
261set_frame_size (ew)
262 EmacsFrame ew;
07bf635f
RS
263{
264 /* The widget hierarchy is
265
266 argv[0] emacsShell pane Frame-NAME
267 ApplicationShell EmacsShell Paned EmacsFrame
268
269 We accept geometry specs in this order:
270
271 *Frame-NAME.geometry
272 *EmacsFrame.geometry
273 Emacs.geometry
274
275 Other possibilities for widget hierarchies might be
276
277 argv[0] frame pane Frame-NAME
278 ApplicationShell EmacsShell Paned EmacsFrame
279 or
280 argv[0] Frame-NAME pane Frame-NAME
281 ApplicationShell EmacsShell Paned EmacsFrame
282 or
283 argv[0] Frame-NAME pane emacsTextPane
284 ApplicationShell EmacsFrame Paned EmacsTextPane
285
286 With the current setup, the text-display-area is the part which is
287 an emacs "frame", since that's the only part managed by emacs proper
288 (the menubar and the parent of the menubar and all that sort of thing
289 are managed by lwlib.)
290
291 The EmacsShell widget is simply a replacement for the Shell widget
292 which is able to deal with using an externally-supplied window instead
293 of always creating its own. It is not actually emacs specific, and
294 should possibly have class "Shell" instead of "EmacsShell" to simplify
295 the resources.
296
297 */
298
299 /* Geometry of the AppShell */
300 int app_flags = 0;
301 int app_x = 0;
302 int app_y = 0;
303 unsigned int app_w = 0;
304 unsigned int app_h = 0;
305
306 /* Geometry of the EmacsFrame */
307 int frame_flags = 0;
308 int frame_x = 0;
309 int frame_y = 0;
310 unsigned int frame_w = 0;
311 unsigned int frame_h = 0;
312
313 /* Hairily merged geometry */
314 int x = 0;
315 int y = 0;
316 unsigned int w = ew->emacs_frame.frame->width;
317 unsigned int h = ew->emacs_frame.frame->height;
318 int flags = 0;
319
320 Widget wmshell = get_wm_shell ((Widget) ew);
38971c41
RS
321 /* Each Emacs shell is now independent and top-level. */
322 Widget app_shell = wmshell;
07bf635f 323
07bf635f 324 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
07bf635f 325
8e6208c5 326 /* We don't need this for the moment. The geometry is computed in
edaf359b
FP
327 xfns.c. */
328#if 0
07bf635f
RS
329 /* If the EmacsFrame doesn't have a geometry but the shell does,
330 treat that as the geometry of the frame. (Is this bogus?
331 I'm not sure.) */
332 if (ew->emacs_frame.geometry == 0)
333 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
334
335 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
336 this bogus? I'm not sure.) */
337 if (!ew->emacs_frame.iconic)
338 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
339
340
341 {
342 char *geom = 0;
343 XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
344 if (geom)
345 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
346 }
347
348 if (ew->emacs_frame.geometry)
349 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
350 &frame_x, &frame_y,
351 &frame_w, &frame_h);
352
353 if (first_frame_p)
354 {
355 /* If this is the first frame created:
356 ====================================
357
358 - Use the ApplicationShell's size/position, if specified.
359 (This is "Emacs.geometry", or the "-geometry" command line arg.)
360 - Else use the EmacsFrame's size/position.
361 (This is "*Frame-NAME.geometry")
362
363 - If the AppShell is iconic, the frame should be iconic.
364
365 AppShell comes first so that -geometry always applies to the first
366 frame created, even if there is an "every frame" entry in the
367 resource database.
368 */
369 if (app_flags & (XValue | YValue))
370 {
371 x = app_x; y = app_y;
372 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
373 }
374 else if (frame_flags & (XValue | YValue))
375 {
376 x = frame_x; y = frame_y;
377 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
378 }
379
380 if (app_flags & (WidthValue | HeightValue))
381 {
382 w = app_w; h = app_h;
383 flags |= (app_flags & (WidthValue | HeightValue));
384 }
385 else if (frame_flags & (WidthValue | HeightValue))
386 {
387 w = frame_w; h = frame_h;
388 flags |= (frame_flags & (WidthValue | HeightValue));
389 }
390
391 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
392 if (!ew->emacs_frame.iconic)
393 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
394
395 first_frame_p = False;
396 }
397 else
398 {
399 /* If this is not the first frame created:
400 ========================================
401
402 - use the EmacsFrame's size/position if specified
403 - Otherwise, use the ApplicationShell's size, but not position.
404
405 So that means that one can specify the position of the first frame
406 with "Emacs.geometry" or `-geometry'; but can only specify the
407 position of subsequent frames with "*Frame-NAME.geometry".
408
409 AppShell comes second so that -geometry does not apply to subsequent
410 frames when there is an "every frame" entry in the resource db,
411 but does apply to the first frame.
412 */
413 if (frame_flags & (XValue | YValue))
414 {
415 x = frame_x; y = frame_y;
416 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
417 }
418
419 if (frame_flags & (WidthValue | HeightValue))
420 {
421 w = frame_w; h = frame_h;
422 flags |= (frame_flags & (WidthValue | HeightValue));
423 }
424 else if (app_flags & (WidthValue | HeightValue))
425 {
426 w = app_w;
427 h = app_h;
428 flags |= (app_flags & (WidthValue | HeightValue));
429 }
430 }
edaf359b 431#endif /* 0 */
07bf635f
RS
432 {
433 struct frame* frame = ew->emacs_frame.frame;
434 Dimension pixel_width, pixel_height;
435 char shell_position [32];
436
437 /* Take into account the size of the scrollbar */
54e9e953 438 frame->output_data.x->vertical_scroll_bar_extra
02a162bf
KH
439 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
440 ? 0
441 : FRAME_SCROLL_BAR_PIXEL_WIDTH (frame) > 0
cb642304 442 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (frame)
02a162bf 443 : (FRAME_SCROLL_BAR_COLS (frame)
54e9e953 444 * FONT_WIDTH (frame->output_data.x->font)));
07bf635f
RS
445
446 change_frame_size (frame, h, w, 1, 0);
447 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
448 ew->core.width = pixel_width;
449 ew->core.height = pixel_height;
450
6ae9a3f2 451#if 0 /* xfns.c takes care of this now. */
07bf635f
RS
452 /* If a position was specified, assign it to the shell widget.
453 (Else WM won't do anything with it.)
454 */
455 if (flags & (XValue | YValue))
456 {
457 /* the tricky things with the sign is to make sure that
458 -0 is printed -0. */
459 int len;
460 char *tem;
461 sprintf (shell_position, "=%c%d%c%d",
462 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
463 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
464 len = strlen (shell_position) + 1;
465 tem = (char *) xmalloc (len);
466 strncpy (tem, shell_position, len);
467 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
468 }
469 else if (flags & (WidthValue | HeightValue))
470 {
471 int len;
472 char *tem;
473 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
474 len = strlen (shell_position) + 1;
475 tem = (char *) xmalloc (len);
476 strncpy (tem, shell_position, len);
477 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
478 }
479
480 /* If the geometry spec we're using has W/H components, mark the size
481 in the WM_SIZE_HINTS as user specified. */
482 if (flags & (WidthValue | HeightValue))
483 mark_shell_size_user_specified (wmshell);
484
485 /* Also assign the iconic status of the frame to the Shell, so that
486 the WM sees it. */
487 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
edaf359b 488#endif /* 0 */
07bf635f
RS
489 }
490}
491
cfcd12d6
KH
492/* Nonzero tells update_wm_hints not to do anything
493 (the caller should call update_wm_hints explicitly later.) */
494int update_hints_inhibit;
07bf635f
RS
495
496static void
345a94f9
RS
497update_wm_hints (ew)
498 EmacsFrame ew;
07bf635f
RS
499{
500 Widget wmshell = get_wm_shell ((Widget)ew);
501 int cw;
502 int ch;
503 Dimension rounded_width;
504 Dimension rounded_height;
505 int char_width;
506 int char_height;
507 int base_width;
508 int base_height;
509 int min_rows = 0, min_cols = 0;
510
cfcd12d6
KH
511 if (update_hints_inhibit)
512 return;
513
514#if 0
07bf635f 515 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
cfcd12d6 516#endif
07bf635f
RS
517
518 pixel_to_char_size (ew, ew->core.width, ew->core.height,
519 &char_width, &char_height);
520 char_to_pixel_size (ew, char_width, char_height,
521 &rounded_width, &rounded_height);
522 get_default_char_pixel_size (ew, &cw, &ch);
523
524 base_width = (wmshell->core.width - ew->core.width
525 + (rounded_width - (char_width * cw)));
526 base_height = (wmshell->core.height - ew->core.height
527 + (rounded_height - (char_height * ch)));
528
529 /* This is kind of sleazy, but I can't see how else to tell it to
530 make it mark the WM_SIZE_HINTS size as user specified.
531 */
532/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
533
534 XtVaSetValues (wmshell,
535 XtNbaseWidth, base_width,
536 XtNbaseHeight, base_height,
537 XtNwidthInc, cw,
538 XtNheightInc, ch,
539 XtNminWidth, base_width + min_cols * cw,
540 XtNminHeight, base_height + min_rows * ch,
541 0);
542}
543
544static void
345a94f9
RS
545create_frame_gcs (ew)
546 EmacsFrame ew;
07bf635f 547{
7f18598b 548 struct frame *s = ew->emacs_frame.frame;
07bf635f 549
54e9e953 550 s->output_data.x->normal_gc
85e53327
KH
551 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
552 (unsigned long)0, (XGCValues *)0);
54e9e953 553 s->output_data.x->reverse_gc
85e53327
KH
554 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
555 (unsigned long)0, (XGCValues *)0);
54e9e953 556 s->output_data.x->cursor_gc
85e53327
KH
557 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
558 (unsigned long)0, (XGCValues *)0);
07bf635f
RS
559}
560
1ad2277b
RS
561static char setup_frame_cursor_bits[] =
562{
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
567};
568
07bf635f 569static void
345a94f9
RS
570setup_frame_gcs (ew)
571 EmacsFrame ew;
07bf635f
RS
572{
573 XGCValues gc_values;
574 struct frame* s = ew->emacs_frame.frame;
575 Pixmap blank_stipple, blank_tile;
576
07bf635f
RS
577 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
578 XGetGCValues returns uninitialized data when we query the stipple
579 (instead of None or something sensible) and it makes things hard.
580
581 This should be fixed for real by not querying the GCs but instead having
582 some GC-based cache instead of the current face-based cache which doesn't
583 effectively cache all of the GC settings we need to use.
584 */
585
85e53327
KH
586 blank_stipple
587 = XCreateBitmapFromData (XtDisplay (ew),
588 RootWindowOfScreen (XtScreen (ew)),
589 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
590
591 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
592 never actually get used as a background tile!
593 */
85e53327
KH
594 blank_tile
595 = XCreatePixmapFromBitmapData (XtDisplay(ew),
596 RootWindowOfScreen (XtScreen (ew)),
597 setup_frame_cursor_bits, 2, 2,
598 (unsigned long)0, (unsigned long)1,
599 ew->core.depth);
07bf635f
RS
600
601 /* Normal video */
602 gc_values.font = ew->emacs_frame.font->fid;
603 gc_values.foreground = ew->emacs_frame.foreground_pixel;
604 gc_values.background = ew->core.background_pixel;
605 gc_values.graphics_exposures = False;
606 gc_values.stipple = blank_stipple;
607 gc_values.tile = blank_tile;
54e9e953 608 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
07bf635f
RS
609 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
610 | GCStipple | GCTile),
611 &gc_values);
612
613 /* Reverse video style. */
614 gc_values.font = ew->emacs_frame.font->fid;
615 gc_values.foreground = ew->core.background_pixel;
616 gc_values.background = ew->emacs_frame.foreground_pixel;
617 gc_values.graphics_exposures = False;
618 gc_values.stipple = blank_stipple;
619 gc_values.tile = blank_tile;
54e9e953 620 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
07bf635f
RS
621 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
622 | GCStipple | GCTile),
623 &gc_values);
624
625 /* Cursor has to have an empty stipple. */
626 gc_values.font = ew->emacs_frame.font->fid;
627 gc_values.foreground = ew->core.background_pixel;
628 gc_values.background = ew->emacs_frame.cursor_color;
629 gc_values.graphics_exposures = False;
630 gc_values.tile = blank_tile;
85e53327
KH
631 gc_values.stipple
632 = XCreateBitmapFromData (XtDisplay (ew),
633 RootWindowOfScreen (XtScreen (ew)),
634 setup_frame_cursor_bits, 16, 16);
54e9e953 635 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
07bf635f
RS
636 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
637 | GCStipple | GCTile),
638 &gc_values);
639}
640
641static void
345a94f9
RS
642update_various_frame_slots (ew)
643 EmacsFrame ew;
07bf635f 644{
54e9e953 645 struct x_output *x = ew->emacs_frame.frame->output_data.x;
846dd8ae 646 x->pixel_height = ew->core.height + x->menubar_height;
07bf635f
RS
647 x->pixel_width = ew->core.width;
648 x->internal_border_width = ew->emacs_frame.internal_border_width;
649
650}
651
652static void
345a94f9
RS
653update_from_various_frame_slots (ew)
654 EmacsFrame ew;
07bf635f 655{
54e9e953 656 struct x_output *x = ew->emacs_frame.frame->output_data.x;
846dd8ae 657 ew->core.height = x->pixel_height - x->menubar_height;
07bf635f
RS
658 ew->core.width = x->pixel_width;
659 ew->core.background_pixel = x->background_pixel;
660 ew->emacs_frame.internal_border_width = x->internal_border_width;
661 ew->emacs_frame.font = x->font;
662 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
663 ew->emacs_frame.cursor_color = x->cursor_pixel;
664 ew->core.border_pixel = x->border_pixel;
665}
666
667static void
345a94f9
RS
668EmacsFrameInitialize (request, new, dum1, dum2)
669 Widget request;
670 Widget new;
671 ArgList dum1;
672 Cardinal *dum2;
07bf635f
RS
673{
674 EmacsFrame ew = (EmacsFrame)new;
675
676 if (!ew->emacs_frame.frame)
677 {
678 fprintf (stderr,
679 "can't create an emacs frame widget without a frame\n");
680 exit (1);
681 }
682
683#if 0 /* done in xfns.c */
684 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
685 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
686 It's unfortunate that we have to do this, but we need to know the font
687 size for frame-sizing purposes before the faces get initialized. If
688 the "default.attributeFont" isn't set, then we use the font of this
689 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
690 the "default" face will use the frame's font if its own is not set,
691 so everything stays in sync -- it's not possible for the frame's font
692 and the default face's font to be different.
693 */
694 {
695 XFontStruct *f = 0;
696 XtResource face_res;
697 face_res.resource_name = "attributeFont";
698 face_res.resource_class = "AttributeFont";
699 face_res.resource_type = XtRFontStruct;
700 face_res.resource_size = sizeof (XFontStruct *);
701 face_res.resource_offset = 0;
702 face_res.default_type = XtRImmediate;
703 face_res.default_addr = 0;
704 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
705 &face_res, 1, NULL, 0);
706
707 if (f)
708 ew->emacs_frame.font = f;
709 else if (! ew->emacs_frame.font)
710 {
711 fprintf (stderr, "emacs frame widget could not load a font\n");
712 exit (1);
713 }
714 }
715
716/* Update the font field in frame */
54e9e953 717 ew->emacs_frame.frame->output_data.x->font = ew->emacs_frame.font;
07bf635f
RS
718#endif
719
720 update_from_various_frame_slots (ew);
721 set_frame_size (ew);
722/*create_frame_gcs (ew);
723 setup_frame_gcs (ew);
724 update_various_frame_slots (ew); */
725}
726
727
728static void
345a94f9
RS
729EmacsFrameRealize (widget, mask, attrs)
730 Widget widget;
731 XtValueMask *mask;
732 XSetWindowAttributes *attrs;
07bf635f
RS
733{
734 EmacsFrame ew = (EmacsFrame)widget;
735
1976080b
RS
736 attrs->event_mask = (STANDARD_EVENT_SET | PropertyChangeMask
737 | SubstructureNotifyMask | SubstructureRedirectMask);
07bf635f
RS
738 *mask |= CWEventMask;
739 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
740 attrs);
741 update_wm_hints (ew);
742}
743
345a94f9 744extern void free_frame_faces (/* struct frame * */);
07bf635f
RS
745
746static void
345a94f9
RS
747EmacsFrameDestroy (widget)
748 Widget widget;
07bf635f
RS
749{
750 EmacsFrame ew = (EmacsFrame) widget;
751 struct frame* s = ew->emacs_frame.frame;
752
753 if (! s) abort ();
54e9e953
KH
754 if (! s->output_data.x) abort ();
755 if (! s->output_data.x->normal_gc) abort ();
07bf635f
RS
756
757 /* this would be called from Fdelete_frame() but it needs to free some
758 stuff after the widget has been finalized but before the widget has
759 been freed. */
760 free_frame_faces (s);
761
49fe12a9 762 BLOCK_INPUT;
07bf635f 763 /* need to be careful that the face-freeing code doesn't free these too */
54e9e953
KH
764 XFreeGC (XtDisplay (widget), s->output_data.x->normal_gc);
765 XFreeGC (XtDisplay (widget), s->output_data.x->reverse_gc);
766 XFreeGC (XtDisplay (widget), s->output_data.x->cursor_gc);
49fe12a9 767 UNBLOCK_INPUT;
07bf635f
RS
768}
769
770void
345a94f9
RS
771EmacsFrameResize (widget)
772 Widget widget;
07bf635f
RS
773{
774 EmacsFrame ew = (EmacsFrame)widget;
775 struct frame *f = ew->emacs_frame.frame;
776 int columns;
777 int rows;
778
779 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
231108d0 780 change_frame_size (f, rows, columns, 0, 1);
07bf635f 781 update_wm_hints (ew);
07bf635f 782 update_various_frame_slots (ew);
49feb47d
RS
783
784 cancel_mouse_face (f);
07bf635f
RS
785}
786
787static Boolean
345a94f9
RS
788EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
789 Widget cur_widget;
790 Widget req_widget;
791 Widget new_widget;
792 ArgList dum1;
793 Cardinal *dum2;
07bf635f
RS
794{
795 EmacsFrame cur = (EmacsFrame)cur_widget;
796 EmacsFrame new = (EmacsFrame)new_widget;
797
798 Boolean needs_a_refresh = False;
799 Boolean has_to_recompute_size;
800 Boolean has_to_recompute_gcs;
801 Boolean has_to_update_hints;
802
803 int char_width, char_height;
804 Dimension pixel_width;
805 Dimension pixel_height;
806
807 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
808 || (cur->emacs_frame.foreground_pixel
809 != new->emacs_frame.foreground_pixel)
810 || (cur->core.background_pixel
811 != new->core.background_pixel)
812 );
813
814 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
815 && cur->core.width == new->core.width
816 && cur->core.height == new->core.height);
817
818 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
819
820 if (has_to_recompute_gcs)
821 {
822 setup_frame_gcs (new);
823 needs_a_refresh = True;
824 }
825
826 if (has_to_recompute_size)
827 {
828 pixel_width = new->core.width;
829 pixel_height = new->core.height;
830 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
831 &char_height);
832 char_to_pixel_size (new, char_width, char_height, &pixel_width,
833 &pixel_height);
834 new->core.width = pixel_width;
835 new->core.height = pixel_height;
836
837 change_frame_size (new->emacs_frame.frame, char_height, char_width,
838 1, 0);
839 needs_a_refresh = True;
840 }
841
842 if (has_to_update_hints)
843 update_wm_hints (new);
844
845 update_various_frame_slots (new);
846
847 /* #### This doesn't work, I haven't been able to find ANY kludge that
848 will let (x-create-frame '((iconic . t))) work. It seems that changes
849 to wm_shell's iconic slot have no effect after it has been realized,
2dd5c7f7 850 and calling XIconifyWindow doesn't work either (even though the window
07bf635f 851 has been created.) Perhaps there is some property we could smash
ac26ca64 852 directly, but I'm sick of this for now.
07bf635f
RS
853 */
854 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
855 {
856 Widget wmshell = get_wm_shell ((Widget) cur);
857 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
858 }
859
860 return needs_a_refresh;
861}
862
863static XtGeometryResult
345a94f9
RS
864EmacsFrameQueryGeometry (widget, request, result)
865 Widget widget;
866 XtWidgetGeometry* request;
867 XtWidgetGeometry* result;
07bf635f
RS
868{
869 EmacsFrame ew = (EmacsFrame)widget;
870
871 int mask = request->request_mode;
872 Dimension ok_width, ok_height;
873
874 if (mask & (CWWidth | CWHeight))
875 {
876 round_size_to_char (ew,
877 (mask & CWWidth) ? request->width : ew->core.width,
878 ((mask & CWHeight) ? request->height
879 : ew->core.height),
880 &ok_width, &ok_height);
881 if ((mask & CWWidth) && (ok_width != request->width))
882 {
883 result->request_mode |= CWWidth;
884 result->width = ok_width;
885 }
886 if ((mask & CWHeight) && (ok_height != request->height))
887 {
888 result->request_mode |= CWHeight;
889 result->height = ok_height;
890 }
891 }
892 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
893}
894
07bf635f
RS
895/* Special entrypoints */
896void
345a94f9
RS
897EmacsFrameSetCharSize (widget, columns, rows)
898 Widget widget;
899 int columns;
900 int rows;
07bf635f
RS
901{
902 EmacsFrame ew = (EmacsFrame) widget;
903 Dimension pixel_width, pixel_height, granted_width, granted_height;
904 XtGeometryResult result;
982a94d9 905 struct frame *f = ew->emacs_frame.frame;
b3ccf2a2
FP
906 Arg al[2];
907 int ac = 0;
908
07bf635f 909 if (columns < 3) columns = 3; /* no way buddy */
07bf635f 910
982a94d9 911 check_frame_size (f, &rows, &columns);
54e9e953 912 f->output_data.x->vertical_scroll_bar_extra
02a162bf
KH
913 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
914 ? 0
915 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
cb642304 916 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
54e9e953 917 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
02a162bf 918
07bf635f 919 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
57aa60d8 920
cfcd12d6
KH
921 /* Manually change the height and width of all our widgets,
922 adjusting each widget by the same increments. */
57aa60d8 923 if (ew->core.width != pixel_width || ew->core.height != pixel_height)
07bf635f 924 {
57aa60d8 925 int hdelta = pixel_height - ew->core.height;
cfcd12d6 926 int wdelta = pixel_width - ew->core.width;
54e9e953
KH
927 int column_widget_height = f->output_data.x->column_widget->core.height;
928 int column_widget_width = f->output_data.x->column_widget->core.width;
929 int outer_widget_height = f->output_data.x->widget->core.height;
930 int outer_widget_width = f->output_data.x->widget->core.width;
931 int old_left = f->output_data.x->widget->core.x;
932 int old_top = f->output_data.x->widget->core.y;
933
934 lw_refigure_widget (f->output_data.x->column_widget, False);
cfcd12d6
KH
935 update_hints_inhibit = 1;
936
b3ccf2a2 937 ac = 0;
e5c001e3
FP
938 XtSetArg (al[ac], XtNheight, pixel_height); ac++;
939 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
940 XtSetValues ((Widget) ew, al, ac);
b3ccf2a2
FP
941
942 ac = 0;
943 XtSetArg (al[ac], XtNheight, column_widget_height + hdelta); ac++;
cfcd12d6 944 XtSetArg (al[ac], XtNwidth, column_widget_width + wdelta); ac++;
54e9e953 945 XtSetValues (f->output_data.x->column_widget, al, ac);
cfcd12d6
KH
946
947 ac = 0;
948 XtSetArg (al[ac], XtNheight, outer_widget_height + hdelta); ac++;
949 XtSetArg (al[ac], XtNwidth, outer_widget_width + wdelta); ac++;
54e9e953 950 XtSetValues (f->output_data.x->widget, al, ac);
cfcd12d6 951
54e9e953 952 lw_refigure_widget (f->output_data.x->column_widget, True);
50d5aeb5 953
cfcd12d6
KH
954 update_hints_inhibit = 0;
955 update_wm_hints (ew);
956
fbf6bf47
RS
957 do_pending_window_change ();
958
50d5aeb5 959 /* These seem to get clobbered. I don't know why. - rms. */
54e9e953
KH
960 f->output_data.x->widget->core.x = old_left;
961 f->output_data.x->widget->core.y = old_top;
07bf635f 962 }
982a94d9
FP
963
964 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
965 receive in the ConfigureNotify event; if we get what we asked
966 for, then the event won't cause the screen to become garbaged, so
967 we have to make sure to do it here. */
968 SET_FRAME_GARBAGED (f);
07bf635f 969}
d793b105 970\f
dfcf069d 971void
d793b105
RS
972widget_store_internal_border (widget)
973 Widget widget;
974{
975 EmacsFrame ew = (EmacsFrame) widget;
976 FRAME_PTR f = ew->emacs_frame.frame;
977
978 ew->emacs_frame.internal_border_width
979 = f->output_data.x->internal_border_width;
980}