(c-macro-display-buffer): Delete special view-mode hack.
[bpt/emacs.git] / src / widget.c
CommitLineData
07bf635f
RS
1/* The emacs frame widget.
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* Emacs 19 face widget ported by Fred Pierresteguy */
21
22#include <stdio.h>
9e65ad77 23#include <config.h>
07bf635f
RS
24#include "lisp.h"
25#include "xterm.h"
26
27#include "frame.h"
28
29#include "dispextern.h"
30
31
32#include <X11/StringDefs.h>
33#include <X11/IntrinsicP.h>
34#include <X11/cursorfont.h>
35#include "widgetprv.h"
65fbf4a3 36#include <X11/ObjectP.h>
07bf635f
RS
37#include <X11/Shell.h>
38#include <X11/ShellP.h>
39
40#define max(a, b) ((a) > (b) ? (a) : (b))
41
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.
49
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.
55
56 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
57 */
58#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
59
60
01492d1b
RS
61static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
62static void EmacsFrameDestroy (/* Widget */);
63static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
64void EmacsFrameResize (/* Widget widget */);
65static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
66 ArgList, Cardinal * */);
67static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
68 XtWidgetGeometry* */);
07bf635f
RS
69
70
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)
75
76static 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},
81
82 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
83 offset (frame), XtRImmediate, 0},
84
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},
105};
106
107#undef offset
108
109/*
110static XtActionsRec
111emacsFrameActionsTable [] = {
112 {"keypress", key_press},
113 {"focus_in", emacs_frame_focus_handler},
114 {"focus_out", emacs_frame_focus_handler},
115};
116
117static char
118emacsFrameTranslations [] = "\
119<KeyPress>: keypress()\n\
120<FocusIn>: focus_in()\n\
121<FocusOut>: focus_out()\n\
122";
123*/
124
125EmacsFrameClassRec 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
159 }
160};
161
162WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
163
164static void
01492d1b
RS
165get_default_char_pixel_size (ew, pixel_width, pixel_height)
166 EmacsFrame ew;
167 int* pixel_width;
168 int* pixel_height;
07bf635f 169{
07bf635f
RS
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);
173}
174
175static void
01492d1b
RS
176pixel_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;
07bf635f
RS
182{
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);
186}
187
188static void
345a94f9
RS
189char_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;
07bf635f
RS
195{
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);
199}
200
201static void
345a94f9
RS
202round_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;
07bf635f
RS
208{
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);
213}
214
215static Widget
345a94f9
RS
216get_wm_shell (w)
217 Widget w;
07bf635f
RS
218{
219 Widget wmshell;
220
221 for (wmshell = XtParent (w);
222 wmshell && !XtIsWMShell (wmshell);
223 wmshell = XtParent (wmshell));
224
225 return wmshell;
226}
227
228static void
345a94f9
RS
229mark_shell_size_user_specified (wmshell)
230 Widget wmshell;
07bf635f
RS
231{
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;
236}
237
238
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.
244 */
245static Boolean first_frame_p = True;
246
247static void
345a94f9
RS
248set_frame_size (ew)
249 EmacsFrame ew;
07bf635f
RS
250{
251 /* The widget hierarchy is
252
253 argv[0] emacsShell pane Frame-NAME
254 ApplicationShell EmacsShell Paned EmacsFrame
255
256 We accept geometry specs in this order:
257
258 *Frame-NAME.geometry
259 *EmacsFrame.geometry
260 Emacs.geometry
261
262 Other possibilities for widget hierarchies might be
263
264 argv[0] frame pane Frame-NAME
265 ApplicationShell EmacsShell Paned EmacsFrame
266 or
267 argv[0] Frame-NAME pane Frame-NAME
268 ApplicationShell EmacsShell Paned EmacsFrame
269 or
270 argv[0] Frame-NAME pane emacsTextPane
271 ApplicationShell EmacsFrame Paned EmacsTextPane
272
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.)
277
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.
283
284 */
285
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;
292
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;
299
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;
306
307 Widget wmshell = get_wm_shell ((Widget) ew);
308 Widget app_shell = XtParent ((Widget) wmshell);
309
310
311 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
312 if (! XtIsSubclass (app_shell, shellWidgetClass)) abort ();
313
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);
319
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);
324
325
326 {
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);
331 }
332
333 if (ew->emacs_frame.geometry)
334 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
335 &frame_x, &frame_y,
336 &frame_w, &frame_h);
337
338 if (first_frame_p)
339 {
340 /* If this is the first frame created:
341 ====================================
342
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")
347
348 - If the AppShell is iconic, the frame should be iconic.
349
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.
353 */
354 if (app_flags & (XValue | YValue))
355 {
356 x = app_x; y = app_y;
357 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
358 }
359 else if (frame_flags & (XValue | YValue))
360 {
361 x = frame_x; y = frame_y;
362 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
363 }
364
365 if (app_flags & (WidthValue | HeightValue))
366 {
367 w = app_w; h = app_h;
368 flags |= (app_flags & (WidthValue | HeightValue));
369 }
370 else if (frame_flags & (WidthValue | HeightValue))
371 {
372 w = frame_w; h = frame_h;
373 flags |= (frame_flags & (WidthValue | HeightValue));
374 }
375
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);
379
380 first_frame_p = False;
381 }
382 else
383 {
384 /* If this is not the first frame created:
385 ========================================
386
387 - use the EmacsFrame's size/position if specified
388 - Otherwise, use the ApplicationShell's size, but not position.
389
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".
393
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.
397 */
398 if (frame_flags & (XValue | YValue))
399 {
400 x = frame_x; y = frame_y;
401 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
402 }
403
404 if (frame_flags & (WidthValue | HeightValue))
405 {
406 w = frame_w; h = frame_h;
407 flags |= (frame_flags & (WidthValue | HeightValue));
408 }
409 else if (app_flags & (WidthValue | HeightValue))
410 {
411 w = app_w;
412 h = app_h;
413 flags |= (app_flags & (WidthValue | HeightValue));
414 }
415 }
416
417 {
418 struct frame* frame = ew->emacs_frame.frame;
419 Dimension pixel_width, pixel_height;
420 char shell_position [32];
421
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);
427
428
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;
433
434
435 /* If a position was specified, assign it to the shell widget.
436 (Else WM won't do anything with it.)
437 */
438 if (flags & (XValue | YValue))
439 {
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);
451 }
452 else if (flags & (WidthValue | HeightValue))
453 {
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);
461 }
462
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);
467
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);
471 }
472}
473
474
475static void
345a94f9
RS
476update_wm_hints (ew)
477 EmacsFrame ew;
07bf635f
RS
478{
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;
489
490 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
491
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);
497
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)));
502
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.
505 */
506/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
507
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,
515 0);
516}
517
518static void
345a94f9
RS
519create_frame_gcs (ew)
520 EmacsFrame ew;
07bf635f
RS
521{
522 struct frame* s = ew->emacs_frame.frame;
523
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);
530}
531
532static void
345a94f9
RS
533setup_frame_gcs (ew)
534 EmacsFrame ew;
07bf635f
RS
535{
536 XGCValues gc_values;
537 struct frame* s = ew->emacs_frame.frame;
538 Pixmap blank_stipple, blank_tile;
539
540 static char cursor_bits[] =
541 {
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
546 };
547
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.
551
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.
555 */
556
557 blank_stipple =
558 XCreateBitmapFromData (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
559 cursor_bits, 2, 2);
560
561 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
562 never actually get used as a background tile!
563 */
564 blank_tile =
565 XCreatePixmapFromBitmapData (XtDisplay(ew),
566 RootWindowOfScreen (XtScreen (ew)),
567 cursor_bits, 2, 2, 0, 1, ew->core.depth);
568
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);
580
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);
592
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);
607}
608
609static void
345a94f9
RS
610update_various_frame_slots (ew)
611 EmacsFrame ew;
07bf635f
RS
612{
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;
617
618}
619
620static void
345a94f9
RS
621update_from_various_frame_slots (ew)
622 EmacsFrame ew;
07bf635f
RS
623{
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;
633}
634
635static void
345a94f9
RS
636EmacsFrameInitialize (request, new, dum1, dum2)
637 Widget request;
638 Widget new;
639 ArgList dum1;
640 Cardinal *dum2;
07bf635f
RS
641{
642 EmacsFrame ew = (EmacsFrame)new;
643
644 if (!ew->emacs_frame.frame)
645 {
646 fprintf (stderr,
647 "can't create an emacs frame widget without a frame\n");
648 exit (1);
649 }
650
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.
661 */
662 {
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);
674
675 if (f)
676 ew->emacs_frame.font = f;
677 else if (! ew->emacs_frame.font)
678 {
679 fprintf (stderr, "emacs frame widget could not load a font\n");
680 exit (1);
681 }
682 }
683
684/* Update the font field in frame */
685 ew->emacs_frame.frame->display.x->font = ew->emacs_frame.font;
686#endif
687
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); */
693}
694
695
696static void
345a94f9
RS
697EmacsFrameRealize (widget, mask, attrs)
698 Widget widget;
699 XtValueMask *mask;
700 XSetWindowAttributes *attrs;
07bf635f
RS
701{
702 EmacsFrame ew = (EmacsFrame)widget;
703
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);
715}
716
345a94f9 717extern void free_frame_faces (/* struct frame * */);
07bf635f
RS
718
719static void
345a94f9
RS
720EmacsFrameDestroy (widget)
721 Widget widget;
07bf635f
RS
722{
723 EmacsFrame ew = (EmacsFrame) widget;
724 struct frame* s = ew->emacs_frame.frame;
725
726 if (! s) abort ();
727 if (! s->display.x) abort ();
728 if (! s->display.x->normal_gc) abort ();
729
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);
734
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);
739}
740
741void
345a94f9
RS
742EmacsFrameResize (widget)
743 Widget widget;
07bf635f
RS
744{
745 EmacsFrame ew = (EmacsFrame)widget;
746 struct frame *f = ew->emacs_frame.frame;
747 int columns;
748 int rows;
749
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);
07bf635f
RS
753 update_various_frame_slots (ew);
754}
755
756static Boolean
345a94f9
RS
757EmacsFrameSetValues (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;
07bf635f
RS
763{
764 EmacsFrame cur = (EmacsFrame)cur_widget;
765 EmacsFrame new = (EmacsFrame)new_widget;
766
767 Boolean needs_a_refresh = False;
768 Boolean has_to_recompute_size;
769 Boolean has_to_recompute_gcs;
770 Boolean has_to_update_hints;
771
772 int char_width, char_height;
773 Dimension pixel_width;
774 Dimension pixel_height;
775
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)
781 );
782
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);
786
787 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
788
789 if (has_to_recompute_gcs)
790 {
791 setup_frame_gcs (new);
792 needs_a_refresh = True;
793 }
794
795 if (has_to_recompute_size)
796 {
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;
805
806 change_frame_size (new->emacs_frame.frame, char_height, char_width,
807 1, 0);
808 needs_a_refresh = True;
809 }
810
811 if (has_to_update_hints)
812 update_wm_hints (new);
813
814 update_various_frame_slots (new);
815
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!
822 */
823 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
824 {
825 Widget wmshell = get_wm_shell ((Widget) cur);
826 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
827 }
828
829 return needs_a_refresh;
830}
831
832static XtGeometryResult
345a94f9
RS
833EmacsFrameQueryGeometry (widget, request, result)
834 Widget widget;
835 XtWidgetGeometry* request;
836 XtWidgetGeometry* result;
07bf635f
RS
837{
838 EmacsFrame ew = (EmacsFrame)widget;
839
840 int mask = request->request_mode;
841 Dimension ok_width, ok_height;
842
843 if (mask & (CWWidth | CWHeight))
844 {
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))
851 {
852 result->request_mode |= CWWidth;
853 result->width = ok_width;
854 }
855 if ((mask & CWHeight) && (ok_height != request->height))
856 {
857 result->request_mode |= CWHeight;
858 result->height = ok_height;
859 }
860 }
861 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
862}
863
07bf635f
RS
864/* Special entrypoints */
865void
345a94f9
RS
866EmacsFrameSetCharSize (widget, columns, rows)
867 Widget widget;
868 int columns;
869 int rows;
07bf635f
RS
870{
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;
876
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)
886 {
887 XtVaSetValues (XtParent ((Widget) ew), XtNwidth, pixel_width, 0);
888 XtVaSetValues ((Widget) ew, XtNwidth, pixel_width, 0);
889 }
890}