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