(cvs-menu): Don't move point. Use popup-menu.
[emacs.git] / src / widget.c
blob9e8672cb57c9ce6766fc7d65aaba240403d8775b
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"
39 #include "window.h"
41 #include "dispextern.h"
42 #include "blockinput.h"
44 #include <X11/StringDefs.h>
45 #include <X11/IntrinsicP.h>
46 #include <X11/cursorfont.h>
47 #include "widgetprv.h"
48 #include <X11/ObjectP.h>
49 #include <X11/Shell.h>
50 #include <X11/ShellP.h>
51 #include "../lwlib/lwlib.h"
53 #define max(a, b) ((a) > (b) ? (a) : (b))
55 /* This sucks: this is the first default that x-faces.el tries. This won't
56 be used unless neither the "Emacs.EmacsFrame" resource nor the
57 "Emacs.EmacsFrame" resource is set; the frame
58 may have the wrong default size if this font doesn't exist, but some other
59 font that x-faces.el does. The workaround is to specify some font in the
60 resource database; I don't know a solution other than duplicating the font-
61 searching code from x-faces.el in this file.
63 This also means that if "Emacs.EmacsFrame" is specified as a non-
64 existent font, then Xt is going to substitute "XtDefaultFont" for it,
65 which is a different size than this one. The solution for this is to
66 make x-faces.el try to use XtDefaultFont. The problem with that is that
67 XtDefaultFont is almost certainly variable-width.
69 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
71 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
74 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
75 static void EmacsFrameDestroy (/* Widget */);
76 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
77 void EmacsFrameResize (/* Widget widget */);
78 static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
79 ArgList, Cardinal * */);
80 static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
81 XtWidgetGeometry* */);
84 #undef XtOffset
85 #define XtOffset(p_type,field) \
86 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
87 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
89 static XtResource resources[] = {
90 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
91 offset (geometry), XtRString, (XtPointer) 0},
92 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
93 offset (iconic), XtRImmediate, (XtPointer) False},
95 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
96 offset (frame), XtRImmediate, 0},
98 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
99 offset (minibuffer), XtRImmediate, (XtPointer)0},
100 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
101 offset (unsplittable), XtRImmediate, (XtPointer)0},
102 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
103 offset (internal_border_width), XtRImmediate, (XtPointer)4},
104 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
105 offset (interline), XtRImmediate, (XtPointer)0},
106 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
107 offset(font),XtRString, DEFAULT_FACE_FONT},
108 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
109 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
110 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
111 offset(cursor_color), XtRString, "XtDefaultForeground"},
112 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
113 offset (bar_cursor), XtRImmediate, (XtPointer)0},
114 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
115 offset (visual_bell), XtRImmediate, (XtPointer)0},
116 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
117 offset (bell_volume), XtRImmediate, (XtPointer)0},
120 #undef offset
123 static XtActionsRec
124 emacsFrameActionsTable [] = {
125 {"keypress", key_press},
126 {"focus_in", emacs_frame_focus_handler},
127 {"focus_out", emacs_frame_focus_handler},
130 static char
131 emacsFrameTranslations [] = "\
132 <KeyPress>: keypress()\n\
133 <FocusIn>: focus_in()\n\
134 <FocusOut>: focus_out()\n\
138 EmacsFrameClassRec emacsFrameClassRec = {
139 { /* core fields */
140 /* superclass */ &widgetClassRec,
141 /* class_name */ "EmacsFrame",
142 /* widget_size */ sizeof(EmacsFrameRec),
143 /* class_initialize */ 0,
144 /* class_part_initialize */ 0,
145 /* class_inited */ FALSE,
146 /* initialize */ EmacsFrameInitialize,
147 /* initialize_hook */ 0,
148 /* realize */ EmacsFrameRealize,
149 /* actions */ 0, /*emacsFrameActionsTable*/
150 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
151 /* resources */ resources,
152 /* resource_count */ XtNumber(resources),
153 /* xrm_class */ NULLQUARK,
154 /* compress_motion */ TRUE,
155 /* compress_exposure */ TRUE,
156 /* compress_enterleave */ TRUE,
157 /* visible_interest */ FALSE,
158 /* destroy */ EmacsFrameDestroy,
159 /* resize */ EmacsFrameResize,
160 /* expose */ XtInheritExpose,
161 /* set_values */ EmacsFrameSetValues,
162 /* set_values_hook */ 0,
163 /* set_values_almost */ XtInheritSetValuesAlmost,
164 /* get_values_hook */ 0,
165 /* accept_focus */ XtInheritAcceptFocus,
166 /* version */ XtVersion,
167 /* callback_private */ 0,
168 /* tm_table */ 0, /*emacsFrameTranslations*/
169 /* query_geometry */ EmacsFrameQueryGeometry,
170 /* display_accelerator */ XtInheritDisplayAccelerator,
171 /* extension */ 0
175 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
177 static void
178 get_default_char_pixel_size (ew, pixel_width, pixel_height)
179 EmacsFrame ew;
180 int* pixel_width;
181 int* pixel_height;
183 struct frame* f = ew->emacs_frame.frame;
184 *pixel_width = FONT_WIDTH (f->output_data.x->font);
185 *pixel_height = f->output_data.x->line_height;
188 static void
189 pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
190 EmacsFrame ew;
191 Dimension pixel_width;
192 Dimension pixel_height;
193 int* char_width;
194 int* char_height;
196 struct frame* f = ew->emacs_frame.frame;
197 *char_width = PIXEL_TO_CHAR_WIDTH (f, (int) pixel_width);
198 *char_height = PIXEL_TO_CHAR_HEIGHT (f, (int) pixel_height);
201 static void
202 char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
203 EmacsFrame ew;
204 int char_width;
205 int char_height;
206 Dimension* pixel_width;
207 Dimension* pixel_height;
209 struct frame* f = ew->emacs_frame.frame;
210 *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
211 *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
214 static void
215 round_size_to_char (ew, in_width, in_height, out_width, out_height)
216 EmacsFrame ew;
217 Dimension in_width;
218 Dimension in_height;
219 Dimension* out_width;
220 Dimension* out_height;
222 int char_width;
223 int char_height;
224 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
225 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
228 static Widget
229 get_wm_shell (w)
230 Widget w;
232 Widget wmshell;
234 for (wmshell = XtParent (w);
235 wmshell && !XtIsWMShell (wmshell);
236 wmshell = XtParent (wmshell));
238 return wmshell;
241 #if 0 /* Currently not used. */
243 static void
244 mark_shell_size_user_specified (wmshell)
245 Widget wmshell;
247 if (! XtIsWMShell (wmshell)) abort ();
248 /* This is kind of sleazy, but I can't see how else to tell it to make it
249 mark the WM_SIZE_HINTS size as user specified when appropriate. */
250 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
253 #endif
256 /* Can't have static frame locals because of some broken compilers.
257 Normally, initializing a variable like this doesn't work in emacs,
258 but it's ok in this file because it must come after lastfile (and
259 thus have its data not go into text space) because Xt needs to
260 write to initialized data objects too.
262 #if 0
263 static Boolean first_frame_p = True;
264 #endif
266 static void
267 set_frame_size (ew)
268 EmacsFrame ew;
270 /* The widget hierarchy is
272 argv[0] emacsShell pane Frame-NAME
273 ApplicationShell EmacsShell Paned EmacsFrame
275 We accept geometry specs in this order:
277 *Frame-NAME.geometry
278 *EmacsFrame.geometry
279 Emacs.geometry
281 Other possibilities for widget hierarchies might be
283 argv[0] frame pane Frame-NAME
284 ApplicationShell EmacsShell Paned EmacsFrame
286 argv[0] Frame-NAME pane Frame-NAME
287 ApplicationShell EmacsShell Paned EmacsFrame
289 argv[0] Frame-NAME pane emacsTextPane
290 ApplicationShell EmacsFrame Paned EmacsTextPane
292 With the current setup, the text-display-area is the part which is
293 an emacs "frame", since that's the only part managed by emacs proper
294 (the menubar and the parent of the menubar and all that sort of thing
295 are managed by lwlib.)
297 The EmacsShell widget is simply a replacement for the Shell widget
298 which is able to deal with using an externally-supplied window instead
299 of always creating its own. It is not actually emacs specific, and
300 should possibly have class "Shell" instead of "EmacsShell" to simplify
301 the resources.
305 /* Hairily merged geometry */
306 unsigned int w = ew->emacs_frame.frame->width;
307 unsigned int h = ew->emacs_frame.frame->height;
309 Widget wmshell = get_wm_shell ((Widget) ew);
310 /* Each Emacs shell is now independent and top-level. */
312 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
314 /* We don't need this for the moment. The geometry is computed in
315 xfns.c. */
316 #if 0
317 /* If the EmacsFrame doesn't have a geometry but the shell does,
318 treat that as the geometry of the frame. (Is this bogus?
319 I'm not sure.) */
320 if (ew->emacs_frame.geometry == 0)
321 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
323 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
324 this bogus? I'm not sure.) */
325 if (!ew->emacs_frame.iconic)
326 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
330 char *geom = 0;
331 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
332 if (geom)
333 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
336 if (ew->emacs_frame.geometry)
337 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
338 &frame_x, &frame_y,
339 &frame_w, &frame_h);
341 if (first_frame_p)
343 /* If this is the first frame created:
344 ====================================
346 - Use the ApplicationShell's size/position, if specified.
347 (This is "Emacs.geometry", or the "-geometry" command line arg.)
348 - Else use the EmacsFrame's size/position.
349 (This is "*Frame-NAME.geometry")
351 - If the AppShell is iconic, the frame should be iconic.
353 AppShell comes first so that -geometry always applies to the first
354 frame created, even if there is an "every frame" entry in the
355 resource database.
357 if (app_flags & (XValue | YValue))
359 x = app_x; y = app_y;
360 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
362 else if (frame_flags & (XValue | YValue))
364 x = frame_x; y = frame_y;
365 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
368 if (app_flags & (WidthValue | HeightValue))
370 w = app_w; h = app_h;
371 flags |= (app_flags & (WidthValue | HeightValue));
373 else if (frame_flags & (WidthValue | HeightValue))
375 w = frame_w; h = frame_h;
376 flags |= (frame_flags & (WidthValue | HeightValue));
379 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
380 if (!ew->emacs_frame.iconic)
381 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
383 first_frame_p = False;
385 else
387 /* If this is not the first frame created:
388 ========================================
390 - use the EmacsFrame's size/position if specified
391 - Otherwise, use the ApplicationShell's size, but not position.
393 So that means that one can specify the position of the first frame
394 with "Emacs.geometry" or `-geometry'; but can only specify the
395 position of subsequent frames with "*Frame-NAME.geometry".
397 AppShell comes second so that -geometry does not apply to subsequent
398 frames when there is an "every frame" entry in the resource db,
399 but does apply to the first frame.
401 if (frame_flags & (XValue | YValue))
403 x = frame_x; y = frame_y;
404 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
407 if (frame_flags & (WidthValue | HeightValue))
409 w = frame_w; h = frame_h;
410 flags |= (frame_flags & (WidthValue | HeightValue));
412 else if (app_flags & (WidthValue | HeightValue))
414 w = app_w;
415 h = app_h;
416 flags |= (app_flags & (WidthValue | HeightValue));
419 #endif /* 0 */
421 struct frame* frame = ew->emacs_frame.frame;
422 Dimension pixel_width, pixel_height;
424 /* Take into account the size of the scrollbar. Always use the
425 number of columns occupied by the scroll bar here otherwise we
426 might end up with a frame width that is not a multiple of the
427 frame's character width which is bad for vertically split
428 windows. */
429 frame->output_data.x->vertical_scroll_bar_extra
430 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
432 : (FRAME_SCROLL_BAR_COLS (frame)
433 * FONT_WIDTH (frame->output_data.x->font)));
435 frame->output_data.x->flags_areas_extra
436 = FRAME_FLAGS_AREA_WIDTH (frame);
438 change_frame_size (frame, h, w, 1, 0, 0);
439 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
440 ew->core.width = pixel_width;
441 ew->core.height = pixel_height;
443 #if 0 /* xfns.c takes care of this now. */
444 /* If a position was specified, assign it to the shell widget.
445 (Else WM won't do anything with it.)
447 if (flags & (XValue | YValue))
449 /* the tricky things with the sign is to make sure that
450 -0 is printed -0. */
451 int len;
452 char *tem;
453 sprintf (shell_position, "=%c%d%c%d",
454 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
455 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
456 len = strlen (shell_position) + 1;
457 tem = (char *) xmalloc (len);
458 strncpy (tem, shell_position, len);
459 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
461 else if (flags & (WidthValue | HeightValue))
463 int len;
464 char *tem;
465 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
466 len = strlen (shell_position) + 1;
467 tem = (char *) xmalloc (len);
468 strncpy (tem, shell_position, len);
469 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
472 /* If the geometry spec we're using has W/H components, mark the size
473 in the WM_SIZE_HINTS as user specified. */
474 if (flags & (WidthValue | HeightValue))
475 mark_shell_size_user_specified (wmshell);
477 /* Also assign the iconic status of the frame to the Shell, so that
478 the WM sees it. */
479 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
480 #endif /* 0 */
484 /* Nonzero tells update_wm_hints not to do anything
485 (the caller should call update_wm_hints explicitly later.) */
486 int update_hints_inhibit;
488 static void
489 update_wm_hints (ew)
490 EmacsFrame ew;
492 Widget wmshell = get_wm_shell ((Widget)ew);
493 int cw;
494 int ch;
495 Dimension rounded_width;
496 Dimension rounded_height;
497 int char_width;
498 int char_height;
499 int base_width;
500 int base_height;
501 int min_rows = 0, min_cols = 0;
503 if (update_hints_inhibit)
504 return;
506 #if 0
507 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
508 #endif
510 pixel_to_char_size (ew, ew->core.width, ew->core.height,
511 &char_width, &char_height);
512 char_to_pixel_size (ew, char_width, char_height,
513 &rounded_width, &rounded_height);
514 get_default_char_pixel_size (ew, &cw, &ch);
516 base_width = (wmshell->core.width - ew->core.width
517 + (rounded_width - (char_width * cw)));
518 base_height = (wmshell->core.height - ew->core.height
519 + (rounded_height - (char_height * ch)));
521 /* This is kind of sleazy, but I can't see how else to tell it to
522 make it mark the WM_SIZE_HINTS size as user specified.
524 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
526 XtVaSetValues (wmshell,
527 XtNbaseWidth, base_width,
528 XtNbaseHeight, base_height,
529 XtNwidthInc, cw,
530 XtNheightInc, ch,
531 XtNminWidth, base_width + min_cols * cw,
532 XtNminHeight, base_height + min_rows * ch,
533 NULL);
536 #if 0
538 static void
539 create_frame_gcs (ew)
540 EmacsFrame ew;
542 struct frame *s = ew->emacs_frame.frame;
544 s->output_data.x->normal_gc
545 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
546 (unsigned long)0, (XGCValues *)0);
547 s->output_data.x->reverse_gc
548 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
549 (unsigned long)0, (XGCValues *)0);
550 s->output_data.x->cursor_gc
551 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
552 (unsigned long)0, (XGCValues *)0);
553 s->output_data.x->black_relief.gc = 0;
554 s->output_data.x->white_relief.gc = 0;
557 #endif /* 0 */
559 static char setup_frame_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 static void
568 setup_frame_gcs (ew)
569 EmacsFrame ew;
571 XGCValues gc_values;
572 struct frame* s = ew->emacs_frame.frame;
573 Pixmap blank_stipple, blank_tile;
575 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
576 XGetGCValues returns uninitialized data when we query the stipple
577 (instead of None or something sensible) and it makes things hard.
579 This should be fixed for real by not querying the GCs but instead having
580 some GC-based cache instead of the current face-based cache which doesn't
581 effectively cache all of the GC settings we need to use.
584 blank_stipple
585 = XCreateBitmapFromData (XtDisplay (ew),
586 RootWindowOfScreen (XtScreen (ew)),
587 setup_frame_cursor_bits, 2, 2);
589 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
590 never actually get used as a background tile!
592 blank_tile
593 = XCreatePixmapFromBitmapData (XtDisplay(ew),
594 RootWindowOfScreen (XtScreen (ew)),
595 setup_frame_cursor_bits, 2, 2,
596 (unsigned long)0, (unsigned long)1,
597 ew->core.depth);
599 /* Normal video */
600 gc_values.font = ew->emacs_frame.font->fid;
601 gc_values.foreground = ew->emacs_frame.foreground_pixel;
602 gc_values.background = ew->core.background_pixel;
603 gc_values.graphics_exposures = False;
604 gc_values.stipple = blank_stipple;
605 gc_values.tile = blank_tile;
606 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
607 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
608 | GCStipple | GCTile),
609 &gc_values);
611 /* Reverse video style. */
612 gc_values.font = ew->emacs_frame.font->fid;
613 gc_values.foreground = ew->core.background_pixel;
614 gc_values.background = ew->emacs_frame.foreground_pixel;
615 gc_values.graphics_exposures = False;
616 gc_values.stipple = blank_stipple;
617 gc_values.tile = blank_tile;
618 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
619 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
620 | GCStipple | GCTile),
621 &gc_values);
623 /* Cursor has to have an empty stipple. */
624 gc_values.font = ew->emacs_frame.font->fid;
625 gc_values.foreground = ew->core.background_pixel;
626 gc_values.background = ew->emacs_frame.cursor_color;
627 gc_values.graphics_exposures = False;
628 gc_values.tile = blank_tile;
629 gc_values.stipple
630 = XCreateBitmapFromData (XtDisplay (ew),
631 RootWindowOfScreen (XtScreen (ew)),
632 setup_frame_cursor_bits, 16, 16);
633 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
634 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
635 | GCStipple | GCTile),
636 &gc_values);
639 static void
640 update_various_frame_slots (ew)
641 EmacsFrame ew;
643 struct x_output *x = ew->emacs_frame.frame->output_data.x;
644 x->pixel_height = ew->core.height + x->menubar_height;
645 x->pixel_width = ew->core.width;
646 x->internal_border_width = ew->emacs_frame.internal_border_width;
650 static void
651 update_from_various_frame_slots (ew)
652 EmacsFrame ew;
654 struct x_output *x = ew->emacs_frame.frame->output_data.x;
655 ew->core.height = x->pixel_height - x->menubar_height;
656 ew->core.width = x->pixel_width;
657 ew->core.background_pixel = x->background_pixel;
658 ew->emacs_frame.internal_border_width = x->internal_border_width;
659 ew->emacs_frame.font = x->font;
660 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
661 ew->emacs_frame.cursor_color = x->cursor_pixel;
662 ew->core.border_pixel = x->border_pixel;
665 static void
666 EmacsFrameInitialize (request, new, dum1, dum2)
667 Widget request;
668 Widget new;
669 ArgList dum1;
670 Cardinal *dum2;
672 EmacsFrame ew = (EmacsFrame)new;
674 if (!ew->emacs_frame.frame)
676 fprintf (stderr,
677 "can't create an emacs frame widget without a frame\n");
678 exit (1);
681 #if 0 /* done in xfns.c */
682 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
683 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
684 It's unfortunate that we have to do this, but we need to know the font
685 size for frame-sizing purposes before the faces get initialized. If
686 the "default.attributeFont" isn't set, then we use the font of this
687 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
688 the "default" face will use the frame's font if its own is not set,
689 so everything stays in sync -- it's not possible for the frame's font
690 and the default face's font to be different.
693 XFontStruct *f = 0;
694 XtResource face_res;
695 face_res.resource_name = "attributeFont";
696 face_res.resource_class = "AttributeFont";
697 face_res.resource_type = XtRFontStruct;
698 face_res.resource_size = sizeof (XFontStruct *);
699 face_res.resource_offset = 0;
700 face_res.default_type = XtRImmediate;
701 face_res.default_addr = 0;
702 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
703 &face_res, 1, NULL, 0);
705 if (f)
706 ew->emacs_frame.font = f;
707 else if (! ew->emacs_frame.font)
709 fprintf (stderr, "emacs frame widget could not load a font\n");
710 exit (1);
714 /* Update the font field in frame */
715 ew->emacs_frame.frame->output_data.x->font = ew->emacs_frame.font;
716 #endif
718 update_from_various_frame_slots (ew);
719 set_frame_size (ew);
720 /*create_frame_gcs (ew);
721 setup_frame_gcs (ew);
722 update_various_frame_slots (ew); */
726 static void
727 EmacsFrameRealize (widget, mask, attrs)
728 Widget widget;
729 XtValueMask *mask;
730 XSetWindowAttributes *attrs;
732 EmacsFrame ew = (EmacsFrame)widget;
734 /* This used to contain SubstructureRedirectMask, but this turns out
735 to be a problem with XIM on Solaris, and events from that mask
736 don't seem to be used. Let's check that. */
737 attrs->event_mask = (STANDARD_EVENT_SET
738 | PropertyChangeMask
739 | SubstructureNotifyMask);
740 *mask |= CWEventMask;
741 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
742 attrs);
743 update_wm_hints (ew);
746 extern void free_frame_faces (/* struct frame * */);
748 static void
749 EmacsFrameDestroy (widget)
750 Widget widget;
752 EmacsFrame ew = (EmacsFrame) widget;
753 struct frame* s = ew->emacs_frame.frame;
755 if (! s) abort ();
756 if (! s->output_data.x) abort ();
757 if (! s->output_data.x->normal_gc) abort ();
759 BLOCK_INPUT;
760 /* need to be careful that the face-freeing code doesn't free these too */
761 XFreeGC (XtDisplay (widget), s->output_data.x->normal_gc);
762 XFreeGC (XtDisplay (widget), s->output_data.x->reverse_gc);
763 XFreeGC (XtDisplay (widget), s->output_data.x->cursor_gc);
764 if (s->output_data.x->white_relief.gc)
765 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
766 if (s->output_data.x->black_relief.gc)
767 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
768 UNBLOCK_INPUT;
771 void
772 EmacsFrameResize (widget)
773 Widget widget;
775 EmacsFrame ew = (EmacsFrame)widget;
776 struct frame *f = ew->emacs_frame.frame;
777 int columns;
778 int rows;
780 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
781 change_frame_size (f, rows, columns, 0, 1, 0);
782 update_wm_hints (ew);
783 update_various_frame_slots (ew);
785 cancel_mouse_face (f);
788 static Boolean
789 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
790 Widget cur_widget;
791 Widget req_widget;
792 Widget new_widget;
793 ArgList dum1;
794 Cardinal *dum2;
796 EmacsFrame cur = (EmacsFrame)cur_widget;
797 EmacsFrame new = (EmacsFrame)new_widget;
799 Boolean needs_a_refresh = False;
800 Boolean has_to_recompute_size;
801 Boolean has_to_recompute_gcs;
802 Boolean has_to_update_hints;
804 int char_width, char_height;
805 Dimension pixel_width;
806 Dimension pixel_height;
808 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
809 || (cur->emacs_frame.foreground_pixel
810 != new->emacs_frame.foreground_pixel)
811 || (cur->core.background_pixel
812 != new->core.background_pixel)
815 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
816 && cur->core.width == new->core.width
817 && cur->core.height == new->core.height);
819 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
821 if (has_to_recompute_gcs)
823 setup_frame_gcs (new);
824 needs_a_refresh = True;
827 if (has_to_recompute_size)
829 pixel_width = new->core.width;
830 pixel_height = new->core.height;
831 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
832 &char_height);
833 char_to_pixel_size (new, char_width, char_height, &pixel_width,
834 &pixel_height);
835 new->core.width = pixel_width;
836 new->core.height = pixel_height;
838 change_frame_size (new->emacs_frame.frame, char_height, char_width,
839 1, 0, 0);
840 needs_a_refresh = True;
843 if (has_to_update_hints)
844 update_wm_hints (new);
846 update_various_frame_slots (new);
848 /* #### This doesn't work, I haven't been able to find ANY kludge that
849 will let (x-create-frame '((iconic . t))) work. It seems that changes
850 to wm_shell's iconic slot have no effect after it has been realized,
851 and calling XIconifyWindow doesn't work either (even though the window
852 has been created.) Perhaps there is some property we could smash
853 directly, but I'm sick of this for now.
855 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
857 Widget wmshell = get_wm_shell ((Widget) cur);
858 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, NULL);
861 return needs_a_refresh;
864 static XtGeometryResult
865 EmacsFrameQueryGeometry (widget, request, result)
866 Widget widget;
867 XtWidgetGeometry* request;
868 XtWidgetGeometry* result;
870 EmacsFrame ew = (EmacsFrame)widget;
872 int mask = request->request_mode;
873 Dimension ok_width, ok_height;
875 if (mask & (CWWidth | CWHeight))
877 round_size_to_char (ew,
878 (mask & CWWidth) ? request->width : ew->core.width,
879 ((mask & CWHeight) ? request->height
880 : ew->core.height),
881 &ok_width, &ok_height);
882 if ((mask & CWWidth) && (ok_width != request->width))
884 result->request_mode |= CWWidth;
885 result->width = ok_width;
887 if ((mask & CWHeight) && (ok_height != request->height))
889 result->request_mode |= CWHeight;
890 result->height = ok_height;
893 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
896 /* Special entrypoints */
897 void
898 EmacsFrameSetCharSize (widget, columns, rows)
899 Widget widget;
900 int columns;
901 int rows;
903 EmacsFrame ew = (EmacsFrame) widget;
904 Dimension pixel_width, pixel_height;
905 struct frame *f = ew->emacs_frame.frame;
906 Arg al[10];
907 int ac = 0;
909 if (columns < 3) columns = 3; /* no way buddy */
911 check_frame_size (f, &rows, &columns);
912 f->output_data.x->vertical_scroll_bar_extra
913 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
915 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
917 f->output_data.x->flags_areas_extra
918 = FRAME_FLAGS_AREA_WIDTH (f);
920 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
922 #if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
923 /* Something is really strange here wrt to the border width:
924 Apparently, XtNwidth and XtNheight include the border, so we have
925 to add it here. But the XtNborderWidth set for the widgets has
926 no similarity to what f->output_data.x->border_width is set to. */
927 XtVaGetValues (widget, XtNborderWidth, &border_width, NULL);
928 pixel_height += 2 * border_width;
929 pixel_width += 2 * border_width;
930 #endif
932 /* Manually change the height and width of all our widgets,
933 adjusting each widget by the same increments. */
934 if (ew->core.width != pixel_width
935 || ew->core.height != pixel_height)
937 int hdelta = pixel_height - ew->core.height;
938 int wdelta = pixel_width - ew->core.width;
939 int column_widget_height = f->output_data.x->column_widget->core.height;
940 int column_widget_width = f->output_data.x->column_widget->core.width;
941 int outer_widget_height = f->output_data.x->widget->core.height;
942 int outer_widget_width = f->output_data.x->widget->core.width;
943 int old_left = f->output_data.x->widget->core.x;
944 int old_top = f->output_data.x->widget->core.y;
946 lw_refigure_widget (f->output_data.x->column_widget, False);
947 update_hints_inhibit = 1;
949 /* Do parents first, otherwise LessTif's geometry
950 management enters an infinite loop (as of 2000-01-15). */
951 XtVaSetValues (f->output_data.x->widget,
952 XtNheight, outer_widget_height + hdelta,
953 XtNwidth, outer_widget_width + wdelta, NULL);
954 XtVaSetValues (f->output_data.x->column_widget,
955 XtNheight, column_widget_height + hdelta,
956 XtNwidth, column_widget_width + wdelta, NULL);
957 XtVaSetValues ((Widget) ew,
958 XtNheight, pixel_height,
959 XtNwidth, pixel_width, NULL);
961 lw_refigure_widget (f->output_data.x->column_widget, True);
963 update_hints_inhibit = 0;
964 update_wm_hints (ew);
966 /* These seem to get clobbered. I don't know why. - rms. */
967 f->output_data.x->widget->core.x = old_left;
968 f->output_data.x->widget->core.y = old_top;
971 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
972 receive in the ConfigureNotify event; if we get what we asked
973 for, then the event won't cause the screen to become garbaged, so
974 we have to make sure to do it here. */
975 SET_FRAME_GARBAGED (f);
979 void
980 widget_store_internal_border (widget)
981 Widget widget;
983 EmacsFrame ew = (EmacsFrame) widget;
984 FRAME_PTR f = ew->emacs_frame.frame;
986 ew->emacs_frame.internal_border_width
987 = f->output_data.x->internal_border_width;