(x_find_modifier_meanings): Skip zero entries.
[emacs.git] / src / widget.c
blob09fc0f3ecbe1ef1d242094adbd3748eb6aa5009f
1 /* The emacs frame widget.
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Emacs 19 face widget ported by Fred Pierresteguy */
22 #include <stdio.h>
23 #include <config.h>
24 #include "lisp.h"
25 #include "xterm.h"
27 #include "frame.h"
29 #include "dispextern.h"
32 #include <X11/StringDefs.h>
33 #include <X11/IntrinsicP.h>
34 #include <X11/cursorfont.h>
35 #include "widgetprv.h"
36 #include <X11/ObjectP.h>
37 #include <X11/Shell.h>
38 #include <X11/ShellP.h>
40 #define max(a, b) ((a) > (b) ? (a) : (b))
42 /* This sucks: this is the first default that x-faces.el tries. This won't
43 be used unless neither the "Emacs.EmacsFrame" resource nor the
44 "Emacs.EmacsFrame" resource is set; the frame
45 may have the wrong default size if this font doesn't exist, but some other
46 font that x-faces.el does. The workaround is to specify some font in the
47 resource database; I don't know a solution other than duplicating the font-
48 searching code from x-faces.el in this file.
50 This also means that if "Emacs.EmacsFrame" is specified as a non-
51 existent font, then Xt is going to substitute "XtDefaultFont" for it,
52 which is a different size than this one. The solution for this is to
53 make x-faces.el try to use XtDefaultFont. The problem with that is that
54 XtDefaultFont is almost certainly variable-width.
56 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
58 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
61 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
62 static void EmacsFrameDestroy (/* Widget */);
63 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
64 void EmacsFrameResize (/* Widget widget */);
65 static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
66 ArgList, Cardinal * */);
67 static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
68 XtWidgetGeometry* */);
71 #undef XtOffset
72 #define XtOffset(p_type,field) \
73 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
74 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
76 static XtResource resources[] = {
77 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
78 offset (geometry), XtRString, (XtPointer) 0},
79 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
80 offset (iconic), XtRImmediate, (XtPointer) False},
82 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
83 offset (frame), XtRImmediate, 0},
85 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
86 offset (minibuffer), XtRImmediate, (XtPointer)0},
87 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
88 offset (unsplittable), XtRImmediate, (XtPointer)0},
89 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
90 offset (internal_border_width), XtRImmediate, (XtPointer)4},
91 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
92 offset (interline), XtRImmediate, (XtPointer)0},
93 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
94 offset(font),XtRString, DEFAULT_FACE_FONT},
95 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
96 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
97 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
98 offset(cursor_color), XtRString, "XtDefaultForeground"},
99 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
100 offset (bar_cursor), XtRImmediate, (XtPointer)0},
101 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
102 offset (visual_bell), XtRImmediate, (XtPointer)0},
103 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
104 offset (bell_volume), XtRImmediate, (XtPointer)0},
107 #undef offset
110 static XtActionsRec
111 emacsFrameActionsTable [] = {
112 {"keypress", key_press},
113 {"focus_in", emacs_frame_focus_handler},
114 {"focus_out", emacs_frame_focus_handler},
117 static char
118 emacsFrameTranslations [] = "\
119 <KeyPress>: keypress()\n\
120 <FocusIn>: focus_in()\n\
121 <FocusOut>: focus_out()\n\
125 EmacsFrameClassRec emacsFrameClassRec = {
126 { /* core fields */
127 /* superclass */ &widgetClassRec,
128 /* class_name */ "EmacsFrame",
129 /* widget_size */ sizeof(EmacsFrameRec),
130 /* class_initialize */ 0,
131 /* class_part_initialize */ 0,
132 /* class_inited */ FALSE,
133 /* initialize */ EmacsFrameInitialize,
134 /* initialize_hook */ 0,
135 /* realize */ EmacsFrameRealize,
136 /* actions */ 0, /*emacsFrameActionsTable*/
137 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
138 /* resources */ resources,
139 /* resource_count */ XtNumber(resources),
140 /* xrm_class */ NULLQUARK,
141 /* compress_motion */ TRUE,
142 /* compress_exposure */ TRUE,
143 /* compress_enterleave */ TRUE,
144 /* visible_interest */ FALSE,
145 /* destroy */ EmacsFrameDestroy,
146 /* resize */ EmacsFrameResize,
147 /* expose */ XtInheritExpose,
148 /* set_values */ EmacsFrameSetValues,
149 /* set_values_hook */ 0,
150 /* set_values_almost */ XtInheritSetValuesAlmost,
151 /* get_values_hook */ 0,
152 /* accept_focus */ XtInheritAcceptFocus,
153 /* version */ XtVersion,
154 /* callback_private */ 0,
155 /* tm_table */ 0, /*emacsFrameTranslations*/
156 /* query_geometry */ EmacsFrameQueryGeometry,
157 /* display_accelerator */ XtInheritDisplayAccelerator,
158 /* extension */ 0
162 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
164 static void
165 get_default_char_pixel_size (ew, pixel_width, pixel_height)
166 EmacsFrame ew;
167 int* pixel_width;
168 int* pixel_height;
170 struct frame* f = ew->emacs_frame.frame;
171 *pixel_width = FONT_WIDTH (f->display.x->font);
172 *pixel_height = FONT_HEIGHT (f->display.x->font);
175 static void
176 pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
177 EmacsFrame ew;
178 Dimension pixel_width;
179 Dimension pixel_height;
180 int* char_width;
181 int* char_height;
183 struct frame* f = ew->emacs_frame.frame;
184 *char_width = PIXEL_TO_CHAR_WIDTH (f, pixel_width);
185 *char_height = PIXEL_TO_CHAR_HEIGHT (f, pixel_height);
188 static void
189 char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
190 EmacsFrame ew;
191 int char_width;
192 int char_height;
193 Dimension* pixel_width;
194 Dimension* pixel_height;
196 struct frame* f = ew->emacs_frame.frame;
197 *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
198 *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
201 static void
202 round_size_to_char (ew, in_width, in_height, out_width, out_height)
203 EmacsFrame ew;
204 Dimension in_width;
205 Dimension in_height;
206 Dimension* out_width;
207 Dimension* out_height;
209 int char_width;
210 int char_height;
211 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
212 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
215 static Widget
216 get_wm_shell (w)
217 Widget w;
219 Widget wmshell;
221 for (wmshell = XtParent (w);
222 wmshell && !XtIsWMShell (wmshell);
223 wmshell = XtParent (wmshell));
225 return wmshell;
228 static void
229 mark_shell_size_user_specified (wmshell)
230 Widget wmshell;
232 if (! XtIsWMShell (wmshell)) abort ();
233 /* This is kind of sleazy, but I can't see how else to tell it to make it
234 mark the WM_SIZE_HINTS size as user specified when appropriate. */
235 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
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.
245 static Boolean first_frame_p = True;
247 static void
248 set_frame_size (ew)
249 EmacsFrame ew;
251 /* The widget hierarchy is
253 argv[0] emacsShell pane Frame-NAME
254 ApplicationShell EmacsShell Paned EmacsFrame
256 We accept geometry specs in this order:
258 *Frame-NAME.geometry
259 *EmacsFrame.geometry
260 Emacs.geometry
262 Other possibilities for widget hierarchies might be
264 argv[0] frame pane Frame-NAME
265 ApplicationShell EmacsShell Paned EmacsFrame
267 argv[0] Frame-NAME pane Frame-NAME
268 ApplicationShell EmacsShell Paned EmacsFrame
270 argv[0] Frame-NAME pane emacsTextPane
271 ApplicationShell EmacsFrame Paned EmacsTextPane
273 With the current setup, the text-display-area is the part which is
274 an emacs "frame", since that's the only part managed by emacs proper
275 (the menubar and the parent of the menubar and all that sort of thing
276 are managed by lwlib.)
278 The EmacsShell widget is simply a replacement for the Shell widget
279 which is able to deal with using an externally-supplied window instead
280 of always creating its own. It is not actually emacs specific, and
281 should possibly have class "Shell" instead of "EmacsShell" to simplify
282 the resources.
286 /* Geometry of the AppShell */
287 int app_flags = 0;
288 int app_x = 0;
289 int app_y = 0;
290 unsigned int app_w = 0;
291 unsigned int app_h = 0;
293 /* Geometry of the EmacsFrame */
294 int frame_flags = 0;
295 int frame_x = 0;
296 int frame_y = 0;
297 unsigned int frame_w = 0;
298 unsigned int frame_h = 0;
300 /* Hairily merged geometry */
301 int x = 0;
302 int y = 0;
303 unsigned int w = ew->emacs_frame.frame->width;
304 unsigned int h = ew->emacs_frame.frame->height;
305 int flags = 0;
307 Widget wmshell = get_wm_shell ((Widget) ew);
308 Widget app_shell = XtParent ((Widget) wmshell);
310 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
311 if (! XtIsSubclass (app_shell, shellWidgetClass)) abort ();
313 /* We don't need this for the momment. The geometry is computed in
314 xfns.c. */
315 #if 0
316 /* If the EmacsFrame doesn't have a geometry but the shell does,
317 treat that as the geometry of the frame. (Is this bogus?
318 I'm not sure.) */
319 if (ew->emacs_frame.geometry == 0)
320 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
322 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
323 this bogus? I'm not sure.) */
324 if (!ew->emacs_frame.iconic)
325 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
329 char *geom = 0;
330 XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
331 if (geom)
332 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
335 if (ew->emacs_frame.geometry)
336 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
337 &frame_x, &frame_y,
338 &frame_w, &frame_h);
340 if (first_frame_p)
342 /* If this is the first frame created:
343 ====================================
345 - Use the ApplicationShell's size/position, if specified.
346 (This is "Emacs.geometry", or the "-geometry" command line arg.)
347 - Else use the EmacsFrame's size/position.
348 (This is "*Frame-NAME.geometry")
350 - If the AppShell is iconic, the frame should be iconic.
352 AppShell comes first so that -geometry always applies to the first
353 frame created, even if there is an "every frame" entry in the
354 resource database.
356 if (app_flags & (XValue | YValue))
358 x = app_x; y = app_y;
359 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
361 else if (frame_flags & (XValue | YValue))
363 x = frame_x; y = frame_y;
364 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
367 if (app_flags & (WidthValue | HeightValue))
369 w = app_w; h = app_h;
370 flags |= (app_flags & (WidthValue | HeightValue));
372 else if (frame_flags & (WidthValue | HeightValue))
374 w = frame_w; h = frame_h;
375 flags |= (frame_flags & (WidthValue | HeightValue));
378 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
379 if (!ew->emacs_frame.iconic)
380 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
382 first_frame_p = False;
384 else
386 /* If this is not the first frame created:
387 ========================================
389 - use the EmacsFrame's size/position if specified
390 - Otherwise, use the ApplicationShell's size, but not position.
392 So that means that one can specify the position of the first frame
393 with "Emacs.geometry" or `-geometry'; but can only specify the
394 position of subsequent frames with "*Frame-NAME.geometry".
396 AppShell comes second so that -geometry does not apply to subsequent
397 frames when there is an "every frame" entry in the resource db,
398 but does apply to the first frame.
400 if (frame_flags & (XValue | YValue))
402 x = frame_x; y = frame_y;
403 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
406 if (frame_flags & (WidthValue | HeightValue))
408 w = frame_w; h = frame_h;
409 flags |= (frame_flags & (WidthValue | HeightValue));
411 else if (app_flags & (WidthValue | HeightValue))
413 w = app_w;
414 h = app_h;
415 flags |= (app_flags & (WidthValue | HeightValue));
418 #endif /* 0 */
420 struct frame* frame = ew->emacs_frame.frame;
421 Dimension pixel_width, pixel_height;
422 char shell_position [32];
424 /* Take into account the size of the scrollbar */
425 frame->display.x->vertical_scroll_bar_extra
426 = (FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
427 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (frame)
428 : 0);
431 change_frame_size (frame, h, w, 1, 0);
432 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
433 ew->core.width = pixel_width;
434 ew->core.height = pixel_height;
436 /* Compute the geometry of the toplevel shell because on some platforms
437 when the geometry is not set, the widget children are resized. */
439 int len;
440 char *tem;
441 Arg al[2];
442 int ac = 0;
444 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
445 len = strlen (shell_position) + 1;
446 tem = (char *) xmalloc (len);
447 strncpy (tem, shell_position, len);
448 XtSetArg (al[ac], XtNgeometry, tem); ac++;
449 XtSetValues (wmshell, al, ac);
452 #if 0 /* We don't need this also. */
453 /* If a position was specified, assign it to the shell widget.
454 (Else WM won't do anything with it.)
456 if (flags & (XValue | YValue))
458 /* the tricky things with the sign is to make sure that
459 -0 is printed -0. */
460 int len;
461 char *tem;
462 sprintf (shell_position, "=%c%d%c%d",
463 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
464 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
465 len = strlen (shell_position) + 1;
466 tem = (char *) xmalloc (len);
467 strncpy (tem, shell_position, len);
468 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
470 else if (flags & (WidthValue | HeightValue))
472 int len;
473 char *tem;
474 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
475 len = strlen (shell_position) + 1;
476 tem = (char *) xmalloc (len);
477 strncpy (tem, shell_position, len);
478 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
481 /* If the geometry spec we're using has W/H components, mark the size
482 in the WM_SIZE_HINTS as user specified. */
483 if (flags & (WidthValue | HeightValue))
484 mark_shell_size_user_specified (wmshell);
486 /* Also assign the iconic status of the frame to the Shell, so that
487 the WM sees it. */
488 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
489 #endif /* 0 */
494 static void
495 update_wm_hints (ew)
496 EmacsFrame ew;
498 Widget wmshell = get_wm_shell ((Widget)ew);
499 int cw;
500 int ch;
501 Dimension rounded_width;
502 Dimension rounded_height;
503 int char_width;
504 int char_height;
505 int base_width;
506 int base_height;
507 int min_rows = 0, min_cols = 0;
509 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
511 pixel_to_char_size (ew, ew->core.width, ew->core.height,
512 &char_width, &char_height);
513 char_to_pixel_size (ew, char_width, char_height,
514 &rounded_width, &rounded_height);
515 get_default_char_pixel_size (ew, &cw, &ch);
517 base_width = (wmshell->core.width - ew->core.width
518 + (rounded_width - (char_width * cw)));
519 base_height = (wmshell->core.height - ew->core.height
520 + (rounded_height - (char_height * ch)));
522 /* This is kind of sleazy, but I can't see how else to tell it to
523 make it mark the WM_SIZE_HINTS size as user specified.
525 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
527 XtVaSetValues (wmshell,
528 XtNbaseWidth, base_width,
529 XtNbaseHeight, base_height,
530 XtNwidthInc, cw,
531 XtNheightInc, ch,
532 XtNminWidth, base_width + min_cols * cw,
533 XtNminHeight, base_height + min_rows * ch,
537 static void
538 create_frame_gcs (ew)
539 EmacsFrame ew;
541 struct frame* s = ew->emacs_frame.frame;
543 s->display.x->normal_gc =
544 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
545 s->display.x->reverse_gc =
546 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
547 s->display.x->cursor_gc =
548 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
551 static void
552 setup_frame_gcs (ew)
553 EmacsFrame ew;
555 XGCValues gc_values;
556 struct frame* s = ew->emacs_frame.frame;
557 Pixmap blank_stipple, blank_tile;
559 static char cursor_bits[] =
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
567 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
568 XGetGCValues returns uninitialized data when we query the stipple
569 (instead of None or something sensible) and it makes things hard.
571 This should be fixed for real by not querying the GCs but instead having
572 some GC-based cache instead of the current face-based cache which doesn't
573 effectively cache all of the GC settings we need to use.
576 blank_stipple =
577 XCreateBitmapFromData (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
578 cursor_bits, 2, 2);
580 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
581 never actually get used as a background tile!
583 blank_tile =
584 XCreatePixmapFromBitmapData (XtDisplay(ew),
585 RootWindowOfScreen (XtScreen (ew)),
586 cursor_bits, 2, 2, 0, 1, ew->core.depth);
588 /* Normal video */
589 gc_values.font = ew->emacs_frame.font->fid;
590 gc_values.foreground = ew->emacs_frame.foreground_pixel;
591 gc_values.background = ew->core.background_pixel;
592 gc_values.graphics_exposures = False;
593 gc_values.stipple = blank_stipple;
594 gc_values.tile = blank_tile;
595 XChangeGC (XtDisplay (ew), s->display.x->normal_gc,
596 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
597 | GCStipple | GCTile),
598 &gc_values);
600 /* Reverse video style. */
601 gc_values.font = ew->emacs_frame.font->fid;
602 gc_values.foreground = ew->core.background_pixel;
603 gc_values.background = ew->emacs_frame.foreground_pixel;
604 gc_values.graphics_exposures = False;
605 gc_values.stipple = blank_stipple;
606 gc_values.tile = blank_tile;
607 XChangeGC (XtDisplay (ew), s->display.x->reverse_gc,
608 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
609 | GCStipple | GCTile),
610 &gc_values);
612 /* Cursor has to have an empty stipple. */
613 gc_values.font = ew->emacs_frame.font->fid;
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;
618 gc_values.stipple =
619 XCreateBitmapFromData (XtDisplay (ew),
620 RootWindowOfScreen (XtScreen (ew)),
621 cursor_bits, 16, 16);
622 XChangeGC (XtDisplay (ew), s->display.x->cursor_gc,
623 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
624 | GCStipple | GCTile),
625 &gc_values);
628 static void
629 update_various_frame_slots (ew)
630 EmacsFrame ew;
632 struct x_display* x = ew->emacs_frame.frame->display.x;
633 x->pixel_height = ew->core.height;
634 x->pixel_width = ew->core.width;
635 x->internal_border_width = ew->emacs_frame.internal_border_width;
639 static void
640 update_from_various_frame_slots (ew)
641 EmacsFrame ew;
643 struct x_display* x = ew->emacs_frame.frame->display.x;
644 ew->core.height = x->pixel_height;
645 ew->core.width = x->pixel_width;
646 ew->core.background_pixel = x->background_pixel;
647 ew->emacs_frame.internal_border_width = x->internal_border_width;
648 ew->emacs_frame.font = x->font;
649 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
650 ew->emacs_frame.cursor_color = x->cursor_pixel;
651 ew->core.border_pixel = x->border_pixel;
654 static void
655 EmacsFrameInitialize (request, new, dum1, dum2)
656 Widget request;
657 Widget new;
658 ArgList dum1;
659 Cardinal *dum2;
661 EmacsFrame ew = (EmacsFrame)new;
663 if (!ew->emacs_frame.frame)
665 fprintf (stderr,
666 "can't create an emacs frame widget without a frame\n");
667 exit (1);
670 #if 0 /* done in xfns.c */
671 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
672 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
673 It's unfortunate that we have to do this, but we need to know the font
674 size for frame-sizing purposes before the faces get initialized. If
675 the "default.attributeFont" isn't set, then we use the font of this
676 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
677 the "default" face will use the frame's font if its own is not set,
678 so everything stays in sync -- it's not possible for the frame's font
679 and the default face's font to be different.
682 XFontStruct *f = 0;
683 XtResource face_res;
684 face_res.resource_name = "attributeFont";
685 face_res.resource_class = "AttributeFont";
686 face_res.resource_type = XtRFontStruct;
687 face_res.resource_size = sizeof (XFontStruct *);
688 face_res.resource_offset = 0;
689 face_res.default_type = XtRImmediate;
690 face_res.default_addr = 0;
691 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
692 &face_res, 1, NULL, 0);
694 if (f)
695 ew->emacs_frame.font = f;
696 else if (! ew->emacs_frame.font)
698 fprintf (stderr, "emacs frame widget could not load a font\n");
699 exit (1);
703 /* Update the font field in frame */
704 ew->emacs_frame.frame->display.x->font = ew->emacs_frame.font;
705 #endif
707 update_from_various_frame_slots (ew);
708 set_frame_size (ew);
709 /*create_frame_gcs (ew);
710 setup_frame_gcs (ew);
711 update_various_frame_slots (ew); */
715 static void
716 EmacsFrameRealize (widget, mask, attrs)
717 Widget widget;
718 XtValueMask *mask;
719 XSetWindowAttributes *attrs;
721 EmacsFrame ew = (EmacsFrame)widget;
723 attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
724 ButtonReleaseMask | StructureNotifyMask |
725 FocusChangeMask | PointerMotionHintMask |
726 PointerMotionMask | LeaveWindowMask | EnterWindowMask |
727 VisibilityChangeMask | PropertyChangeMask |
728 StructureNotifyMask | SubstructureNotifyMask |
729 SubstructureRedirectMask);
730 *mask |= CWEventMask;
731 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
732 attrs);
733 update_wm_hints (ew);
736 extern void free_frame_faces (/* struct frame * */);
738 static void
739 EmacsFrameDestroy (widget)
740 Widget widget;
742 EmacsFrame ew = (EmacsFrame) widget;
743 struct frame* s = ew->emacs_frame.frame;
745 if (! s) abort ();
746 if (! s->display.x) abort ();
747 if (! s->display.x->normal_gc) abort ();
749 /* this would be called from Fdelete_frame() but it needs to free some
750 stuff after the widget has been finalized but before the widget has
751 been freed. */
752 free_frame_faces (s);
754 /* need to be careful that the face-freeing code doesn't free these too */
755 XFreeGC (XtDisplay (widget), s->display.x->normal_gc);
756 XFreeGC (XtDisplay (widget), s->display.x->reverse_gc);
757 XFreeGC (XtDisplay (widget), s->display.x->cursor_gc);
760 void
761 EmacsFrameResize (widget)
762 Widget widget;
764 EmacsFrame ew = (EmacsFrame)widget;
765 struct frame *f = ew->emacs_frame.frame;
766 int columns;
767 int rows;
769 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
770 change_frame_size (f, rows, columns, 1, 0);
771 update_wm_hints (ew);
772 update_various_frame_slots (ew);
775 static Boolean
776 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
777 Widget cur_widget;
778 Widget req_widget;
779 Widget new_widget;
780 ArgList dum1;
781 Cardinal *dum2;
783 EmacsFrame cur = (EmacsFrame)cur_widget;
784 EmacsFrame new = (EmacsFrame)new_widget;
786 Boolean needs_a_refresh = False;
787 Boolean has_to_recompute_size;
788 Boolean has_to_recompute_gcs;
789 Boolean has_to_update_hints;
791 int char_width, char_height;
792 Dimension pixel_width;
793 Dimension pixel_height;
795 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
796 || (cur->emacs_frame.foreground_pixel
797 != new->emacs_frame.foreground_pixel)
798 || (cur->core.background_pixel
799 != new->core.background_pixel)
802 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
803 && cur->core.width == new->core.width
804 && cur->core.height == new->core.height);
806 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
808 if (has_to_recompute_gcs)
810 setup_frame_gcs (new);
811 needs_a_refresh = True;
814 if (has_to_recompute_size)
816 pixel_width = new->core.width;
817 pixel_height = new->core.height;
818 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
819 &char_height);
820 char_to_pixel_size (new, char_width, char_height, &pixel_width,
821 &pixel_height);
822 new->core.width = pixel_width;
823 new->core.height = pixel_height;
825 change_frame_size (new->emacs_frame.frame, char_height, char_width,
826 1, 0);
827 needs_a_refresh = True;
830 if (has_to_update_hints)
831 update_wm_hints (new);
833 update_various_frame_slots (new);
835 /* #### This doesn't work, I haven't been able to find ANY kludge that
836 will let (x-create-frame '((iconic . t))) work. It seems that changes
837 to wm_shell's iconic slot have no effect after it has been realized,
838 and calling XIconifyWindow doesn't work either (even thought the window
839 has been created.) Perhaps there is some property we could smash
840 directly, but I'm sick of this for now. Xt is a steaming pile of shit!
842 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
844 Widget wmshell = get_wm_shell ((Widget) cur);
845 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
848 return needs_a_refresh;
851 static XtGeometryResult
852 EmacsFrameQueryGeometry (widget, request, result)
853 Widget widget;
854 XtWidgetGeometry* request;
855 XtWidgetGeometry* result;
857 EmacsFrame ew = (EmacsFrame)widget;
859 int mask = request->request_mode;
860 Dimension ok_width, ok_height;
862 if (mask & (CWWidth | CWHeight))
864 round_size_to_char (ew,
865 (mask & CWWidth) ? request->width : ew->core.width,
866 ((mask & CWHeight) ? request->height
867 : ew->core.height),
868 &ok_width, &ok_height);
869 if ((mask & CWWidth) && (ok_width != request->width))
871 result->request_mode |= CWWidth;
872 result->width = ok_width;
874 if ((mask & CWHeight) && (ok_height != request->height))
876 result->request_mode |= CWHeight;
877 result->height = ok_height;
880 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
883 /* Special entrypoints */
884 void
885 EmacsFrameSetCharSize (widget, columns, rows)
886 Widget widget;
887 int columns;
888 int rows;
890 EmacsFrame ew = (EmacsFrame) widget;
891 Dimension pixel_width, pixel_height, granted_width, granted_height;
892 XtGeometryResult result;
893 struct frame *f = ew->emacs_frame.frame;
895 if (columns < 3) columns = 3; /* no way buddy */
896 if (rows < 3) rows = 3;
898 f->display.x->left_pos = f->display.x->widget->core.x;
899 f->display.x->top_pos = f->display.x->widget->core.y;
901 check_frame_size (f, &rows, &columns);
902 f->display.x->vertical_scroll_bar_extra
903 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
904 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
905 : 0);
906 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
908 /* Dont call XtMakeResize Request. This appears to not work for all
909 the cases.
910 Use XtVaSetValues instead. */
911 #if 0
912 result = XtMakeResizeRequest ((Widget)ew,
913 pixel_width, pixel_height,
914 &granted_width, &granted_height);
915 if (result == XtGeometryAlmost)
916 XtMakeResizeRequest ((Widget) ew, granted_width, granted_height,
917 NULL, NULL);
918 #endif
919 /* Recompute the entire geometry management. */
920 if (ew->core.width != pixel_width || ew->core.height != pixel_height)
922 int hdelta = pixel_height - ew->core.height;
923 int column_widget_height = f->display.x->column_widget->core.height;
924 Arg al[2];
925 int ac = 0;
927 XawPanedSetRefigureMode (f->display.x->column_widget, False);
929 XtSetArg (al[ac], XtNheight, pixel_height); ac++;
930 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
931 XtSetValues ((Widget) ew, al, ac);
932 #if 0
933 XtVaSetValues ((Widget) ew,
934 XtNheight, pixel_height,
935 XtNwidth, pixel_width,
937 #endif
938 XtVaSetValues (f->display.x->column_widget,
939 XtNwidth, pixel_width,
940 XtNheight, column_widget_height + hdelta,
942 XawPanedSetRefigureMode (f->display.x->column_widget, True);
945 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
946 receive in the ConfigureNotify event; if we get what we asked
947 for, then the event won't cause the screen to become garbaged, so
948 we have to make sure to do it here. */
949 SET_FRAME_GARBAGED (f);
951 /* Coordinates of the toplevel widget seem to have been lost.
952 So set it to the rignt values. */
953 XtVaSetValues (f->display.x->widget,
954 XtNx, f->display.x->left_pos,
955 XtNy, f->display.x->top_pos,