Fix calendar-cursor-to-date to handle starred days correctly.
[emacs.git] / src / widget.c
blob298113f6d43527af7d3b279d9f9871b14eec9b53
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);
311 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
312 if (! XtIsSubclass (app_shell, shellWidgetClass)) abort ();
314 /* If the EmacsFrame doesn't have a geometry but the shell does,
315 treat that as the geometry of the frame. (Is this bogus?
316 I'm not sure.) */
317 if (ew->emacs_frame.geometry == 0)
318 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
320 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
321 this bogus? I'm not sure.) */
322 if (!ew->emacs_frame.iconic)
323 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
327 char *geom = 0;
328 XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
329 if (geom)
330 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
333 if (ew->emacs_frame.geometry)
334 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
335 &frame_x, &frame_y,
336 &frame_w, &frame_h);
338 if (first_frame_p)
340 /* If this is the first frame created:
341 ====================================
343 - Use the ApplicationShell's size/position, if specified.
344 (This is "Emacs.geometry", or the "-geometry" command line arg.)
345 - Else use the EmacsFrame's size/position.
346 (This is "*Frame-NAME.geometry")
348 - If the AppShell is iconic, the frame should be iconic.
350 AppShell comes first so that -geometry always applies to the first
351 frame created, even if there is an "every frame" entry in the
352 resource database.
354 if (app_flags & (XValue | YValue))
356 x = app_x; y = app_y;
357 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
359 else if (frame_flags & (XValue | YValue))
361 x = frame_x; y = frame_y;
362 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
365 if (app_flags & (WidthValue | HeightValue))
367 w = app_w; h = app_h;
368 flags |= (app_flags & (WidthValue | HeightValue));
370 else if (frame_flags & (WidthValue | HeightValue))
372 w = frame_w; h = frame_h;
373 flags |= (frame_flags & (WidthValue | HeightValue));
376 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
377 if (!ew->emacs_frame.iconic)
378 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
380 first_frame_p = False;
382 else
384 /* If this is not the first frame created:
385 ========================================
387 - use the EmacsFrame's size/position if specified
388 - Otherwise, use the ApplicationShell's size, but not position.
390 So that means that one can specify the position of the first frame
391 with "Emacs.geometry" or `-geometry'; but can only specify the
392 position of subsequent frames with "*Frame-NAME.geometry".
394 AppShell comes second so that -geometry does not apply to subsequent
395 frames when there is an "every frame" entry in the resource db,
396 but does apply to the first frame.
398 if (frame_flags & (XValue | YValue))
400 x = frame_x; y = frame_y;
401 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
404 if (frame_flags & (WidthValue | HeightValue))
406 w = frame_w; h = frame_h;
407 flags |= (frame_flags & (WidthValue | HeightValue));
409 else if (app_flags & (WidthValue | HeightValue))
411 w = app_w;
412 h = app_h;
413 flags |= (app_flags & (WidthValue | HeightValue));
418 struct frame* frame = ew->emacs_frame.frame;
419 Dimension pixel_width, pixel_height;
420 char shell_position [32];
422 /* Take into account the size of the scrollbar */
423 frame->display.x->vertical_scroll_bar_extra
424 = (FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
425 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (frame)
426 : 0);
429 change_frame_size (frame, h, w, 1, 0);
430 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
431 ew->core.width = pixel_width;
432 ew->core.height = pixel_height;
435 /* If a position was specified, assign it to the shell widget.
436 (Else WM won't do anything with it.)
438 if (flags & (XValue | YValue))
440 /* the tricky things with the sign is to make sure that
441 -0 is printed -0. */
442 int len;
443 char *tem;
444 sprintf (shell_position, "=%c%d%c%d",
445 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
446 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
447 len = strlen (shell_position) + 1;
448 tem = (char *) xmalloc (len);
449 strncpy (tem, shell_position, len);
450 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
452 else if (flags & (WidthValue | HeightValue))
454 int len;
455 char *tem;
456 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
457 len = strlen (shell_position) + 1;
458 tem = (char *) xmalloc (len);
459 strncpy (tem, shell_position, len);
460 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
463 /* If the geometry spec we're using has W/H components, mark the size
464 in the WM_SIZE_HINTS as user specified. */
465 if (flags & (WidthValue | HeightValue))
466 mark_shell_size_user_specified (wmshell);
468 /* Also assign the iconic status of the frame to the Shell, so that
469 the WM sees it. */
470 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
475 static void
476 update_wm_hints (ew)
477 EmacsFrame ew;
479 Widget wmshell = get_wm_shell ((Widget)ew);
480 int cw;
481 int ch;
482 Dimension rounded_width;
483 Dimension rounded_height;
484 int char_width;
485 int char_height;
486 int base_width;
487 int base_height;
488 int min_rows = 0, min_cols = 0;
490 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
492 pixel_to_char_size (ew, ew->core.width, ew->core.height,
493 &char_width, &char_height);
494 char_to_pixel_size (ew, char_width, char_height,
495 &rounded_width, &rounded_height);
496 get_default_char_pixel_size (ew, &cw, &ch);
498 base_width = (wmshell->core.width - ew->core.width
499 + (rounded_width - (char_width * cw)));
500 base_height = (wmshell->core.height - ew->core.height
501 + (rounded_height - (char_height * ch)));
503 /* This is kind of sleazy, but I can't see how else to tell it to
504 make it mark the WM_SIZE_HINTS size as user specified.
506 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
508 XtVaSetValues (wmshell,
509 XtNbaseWidth, base_width,
510 XtNbaseHeight, base_height,
511 XtNwidthInc, cw,
512 XtNheightInc, ch,
513 XtNminWidth, base_width + min_cols * cw,
514 XtNminHeight, base_height + min_rows * ch,
518 static void
519 create_frame_gcs (ew)
520 EmacsFrame ew;
522 struct frame* s = ew->emacs_frame.frame;
524 s->display.x->normal_gc =
525 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
526 s->display.x->reverse_gc =
527 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
528 s->display.x->cursor_gc =
529 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
532 static void
533 setup_frame_gcs (ew)
534 EmacsFrame ew;
536 XGCValues gc_values;
537 struct frame* s = ew->emacs_frame.frame;
538 Pixmap blank_stipple, blank_tile;
540 static char cursor_bits[] =
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
548 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
549 XGetGCValues returns uninitialized data when we query the stipple
550 (instead of None or something sensible) and it makes things hard.
552 This should be fixed for real by not querying the GCs but instead having
553 some GC-based cache instead of the current face-based cache which doesn't
554 effectively cache all of the GC settings we need to use.
557 blank_stipple =
558 XCreateBitmapFromData (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
559 cursor_bits, 2, 2);
561 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
562 never actually get used as a background tile!
564 blank_tile =
565 XCreatePixmapFromBitmapData (XtDisplay(ew),
566 RootWindowOfScreen (XtScreen (ew)),
567 cursor_bits, 2, 2, 0, 1, ew->core.depth);
569 /* Normal video */
570 gc_values.font = ew->emacs_frame.font->fid;
571 gc_values.foreground = ew->emacs_frame.foreground_pixel;
572 gc_values.background = ew->core.background_pixel;
573 gc_values.graphics_exposures = False;
574 gc_values.stipple = blank_stipple;
575 gc_values.tile = blank_tile;
576 XChangeGC (XtDisplay (ew), s->display.x->normal_gc,
577 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
578 | GCStipple | GCTile),
579 &gc_values);
581 /* Reverse video style. */
582 gc_values.font = ew->emacs_frame.font->fid;
583 gc_values.foreground = ew->core.background_pixel;
584 gc_values.background = ew->emacs_frame.foreground_pixel;
585 gc_values.graphics_exposures = False;
586 gc_values.stipple = blank_stipple;
587 gc_values.tile = blank_tile;
588 XChangeGC (XtDisplay (ew), s->display.x->reverse_gc,
589 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
590 | GCStipple | GCTile),
591 &gc_values);
593 /* Cursor has to have an empty stipple. */
594 gc_values.font = ew->emacs_frame.font->fid;
595 gc_values.foreground = ew->core.background_pixel;
596 gc_values.background = ew->emacs_frame.cursor_color;
597 gc_values.graphics_exposures = False;
598 gc_values.tile = blank_tile;
599 gc_values.stipple =
600 XCreateBitmapFromData (XtDisplay (ew),
601 RootWindowOfScreen (XtScreen (ew)),
602 cursor_bits, 16, 16);
603 XChangeGC (XtDisplay (ew), s->display.x->cursor_gc,
604 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
605 | GCStipple | GCTile),
606 &gc_values);
609 static void
610 update_various_frame_slots (ew)
611 EmacsFrame ew;
613 struct x_display* x = ew->emacs_frame.frame->display.x;
614 x->pixel_height = ew->core.height;
615 x->pixel_width = ew->core.width;
616 x->internal_border_width = ew->emacs_frame.internal_border_width;
620 static void
621 update_from_various_frame_slots (ew)
622 EmacsFrame ew;
624 struct x_display* x = ew->emacs_frame.frame->display.x;
625 ew->core.height = x->pixel_height;
626 ew->core.width = x->pixel_width;
627 ew->core.background_pixel = x->background_pixel;
628 ew->emacs_frame.internal_border_width = x->internal_border_width;
629 ew->emacs_frame.font = x->font;
630 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
631 ew->emacs_frame.cursor_color = x->cursor_pixel;
632 ew->core.border_pixel = x->border_pixel;
635 static void
636 EmacsFrameInitialize (request, new, dum1, dum2)
637 Widget request;
638 Widget new;
639 ArgList dum1;
640 Cardinal *dum2;
642 EmacsFrame ew = (EmacsFrame)new;
644 if (!ew->emacs_frame.frame)
646 fprintf (stderr,
647 "can't create an emacs frame widget without a frame\n");
648 exit (1);
651 #if 0 /* done in xfns.c */
652 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
653 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
654 It's unfortunate that we have to do this, but we need to know the font
655 size for frame-sizing purposes before the faces get initialized. If
656 the "default.attributeFont" isn't set, then we use the font of this
657 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
658 the "default" face will use the frame's font if its own is not set,
659 so everything stays in sync -- it's not possible for the frame's font
660 and the default face's font to be different.
663 XFontStruct *f = 0;
664 XtResource face_res;
665 face_res.resource_name = "attributeFont";
666 face_res.resource_class = "AttributeFont";
667 face_res.resource_type = XtRFontStruct;
668 face_res.resource_size = sizeof (XFontStruct *);
669 face_res.resource_offset = 0;
670 face_res.default_type = XtRImmediate;
671 face_res.default_addr = 0;
672 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
673 &face_res, 1, NULL, 0);
675 if (f)
676 ew->emacs_frame.font = f;
677 else if (! ew->emacs_frame.font)
679 fprintf (stderr, "emacs frame widget could not load a font\n");
680 exit (1);
684 /* Update the font field in frame */
685 ew->emacs_frame.frame->display.x->font = ew->emacs_frame.font;
686 #endif
688 update_from_various_frame_slots (ew);
689 set_frame_size (ew);
690 /*create_frame_gcs (ew);
691 setup_frame_gcs (ew);
692 update_various_frame_slots (ew); */
696 static void
697 EmacsFrameRealize (widget, mask, attrs)
698 Widget widget;
699 XtValueMask *mask;
700 XSetWindowAttributes *attrs;
702 EmacsFrame ew = (EmacsFrame)widget;
704 attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
705 ButtonReleaseMask | StructureNotifyMask |
706 FocusChangeMask | PointerMotionHintMask |
707 PointerMotionMask | LeaveWindowMask | EnterWindowMask |
708 VisibilityChangeMask | PropertyChangeMask |
709 StructureNotifyMask | SubstructureNotifyMask |
710 SubstructureRedirectMask);
711 *mask |= CWEventMask;
712 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
713 attrs);
714 update_wm_hints (ew);
717 extern void free_frame_faces (/* struct frame * */);
719 static void
720 EmacsFrameDestroy (widget)
721 Widget widget;
723 EmacsFrame ew = (EmacsFrame) widget;
724 struct frame* s = ew->emacs_frame.frame;
726 if (! s) abort ();
727 if (! s->display.x) abort ();
728 if (! s->display.x->normal_gc) abort ();
730 /* this would be called from Fdelete_frame() but it needs to free some
731 stuff after the widget has been finalized but before the widget has
732 been freed. */
733 free_frame_faces (s);
735 /* need to be careful that the face-freeing code doesn't free these too */
736 XFreeGC (XtDisplay (widget), s->display.x->normal_gc);
737 XFreeGC (XtDisplay (widget), s->display.x->reverse_gc);
738 XFreeGC (XtDisplay (widget), s->display.x->cursor_gc);
741 void
742 EmacsFrameResize (widget)
743 Widget widget;
745 EmacsFrame ew = (EmacsFrame)widget;
746 struct frame *f = ew->emacs_frame.frame;
747 int columns;
748 int rows;
750 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
751 change_frame_size (f, rows, columns, 1, 0);
752 update_wm_hints (ew);
753 update_various_frame_slots (ew);
756 static Boolean
757 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
758 Widget cur_widget;
759 Widget req_widget;
760 Widget new_widget;
761 ArgList dum1;
762 Cardinal *dum2;
764 EmacsFrame cur = (EmacsFrame)cur_widget;
765 EmacsFrame new = (EmacsFrame)new_widget;
767 Boolean needs_a_refresh = False;
768 Boolean has_to_recompute_size;
769 Boolean has_to_recompute_gcs;
770 Boolean has_to_update_hints;
772 int char_width, char_height;
773 Dimension pixel_width;
774 Dimension pixel_height;
776 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
777 || (cur->emacs_frame.foreground_pixel
778 != new->emacs_frame.foreground_pixel)
779 || (cur->core.background_pixel
780 != new->core.background_pixel)
783 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
784 && cur->core.width == new->core.width
785 && cur->core.height == new->core.height);
787 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
789 if (has_to_recompute_gcs)
791 setup_frame_gcs (new);
792 needs_a_refresh = True;
795 if (has_to_recompute_size)
797 pixel_width = new->core.width;
798 pixel_height = new->core.height;
799 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
800 &char_height);
801 char_to_pixel_size (new, char_width, char_height, &pixel_width,
802 &pixel_height);
803 new->core.width = pixel_width;
804 new->core.height = pixel_height;
806 change_frame_size (new->emacs_frame.frame, char_height, char_width,
807 1, 0);
808 needs_a_refresh = True;
811 if (has_to_update_hints)
812 update_wm_hints (new);
814 update_various_frame_slots (new);
816 /* #### This doesn't work, I haven't been able to find ANY kludge that
817 will let (x-create-frame '((iconic . t))) work. It seems that changes
818 to wm_shell's iconic slot have no effect after it has been realized,
819 and calling XIconifyWindow doesn't work either (even thought the window
820 has been created.) Perhaps there is some property we could smash
821 directly, but I'm sick of this for now. Xt is a steaming pile of shit!
823 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
825 Widget wmshell = get_wm_shell ((Widget) cur);
826 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
829 return needs_a_refresh;
832 static XtGeometryResult
833 EmacsFrameQueryGeometry (widget, request, result)
834 Widget widget;
835 XtWidgetGeometry* request;
836 XtWidgetGeometry* result;
838 EmacsFrame ew = (EmacsFrame)widget;
840 int mask = request->request_mode;
841 Dimension ok_width, ok_height;
843 if (mask & (CWWidth | CWHeight))
845 round_size_to_char (ew,
846 (mask & CWWidth) ? request->width : ew->core.width,
847 ((mask & CWHeight) ? request->height
848 : ew->core.height),
849 &ok_width, &ok_height);
850 if ((mask & CWWidth) && (ok_width != request->width))
852 result->request_mode |= CWWidth;
853 result->width = ok_width;
855 if ((mask & CWHeight) && (ok_height != request->height))
857 result->request_mode |= CWHeight;
858 result->height = ok_height;
861 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
864 /* Special entrypoints */
865 void
866 EmacsFrameSetCharSize (widget, columns, rows)
867 Widget widget;
868 int columns;
869 int rows;
871 EmacsFrame ew = (EmacsFrame) widget;
872 Dimension pixel_width, pixel_height, granted_width, granted_height;
873 XtGeometryResult result;
874 if (columns < 3) columns = 3; /* no way buddy */
875 if (rows < 3) rows = 3;
877 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
878 result = XtMakeResizeRequest ((Widget)ew,
879 pixel_width, pixel_height,
880 &granted_width, &granted_height);
881 if (result == XtGeometryAlmost)
882 XtMakeResizeRequest ((Widget) ew, granted_width, granted_height,
883 NULL, NULL);
884 /* damn Paned widget won't ever change its width. Force it. */
885 if (ew->core.width != pixel_width)
887 XtVaSetValues (XtParent ((Widget) ew), XtNwidth, pixel_width, 0);
888 XtVaSetValues ((Widget) ew, XtNwidth, pixel_width, 0);