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