(Vafter_change_functions, Vbefore_change_functions): Declared.
[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);
34216706 172 *pixel_height = f->display.x->line_height;
07bf635f
RS
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
07bf635f
RS
310 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
311 if (! XtIsSubclass (app_shell, shellWidgetClass)) abort ();
312
edaf359b
FP
313 /* We don't need this for the momment. The geometry is computed in
314 xfns.c. */
315#if 0
07bf635f
RS
316 /* If the EmacsFrame doesn't have a geometry but the shell does,
317 treat that as the geometry of the frame. (Is this bogus?
318 I'm not sure.) */
319 if (ew->emacs_frame.geometry == 0)
320 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
321
322 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
323 this bogus? I'm not sure.) */
324 if (!ew->emacs_frame.iconic)
325 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
326
327
328 {
329 char *geom = 0;
330 XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
331 if (geom)
332 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
333 }
334
335 if (ew->emacs_frame.geometry)
336 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
337 &frame_x, &frame_y,
338 &frame_w, &frame_h);
339
340 if (first_frame_p)
341 {
342 /* If this is the first frame created:
343 ====================================
344
345 - Use the ApplicationShell's size/position, if specified.
346 (This is "Emacs.geometry", or the "-geometry" command line arg.)
347 - Else use the EmacsFrame's size/position.
348 (This is "*Frame-NAME.geometry")
349
350 - If the AppShell is iconic, the frame should be iconic.
351
352 AppShell comes first so that -geometry always applies to the first
353 frame created, even if there is an "every frame" entry in the
354 resource database.
355 */
356 if (app_flags & (XValue | YValue))
357 {
358 x = app_x; y = app_y;
359 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
360 }
361 else if (frame_flags & (XValue | YValue))
362 {
363 x = frame_x; y = frame_y;
364 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
365 }
366
367 if (app_flags & (WidthValue | HeightValue))
368 {
369 w = app_w; h = app_h;
370 flags |= (app_flags & (WidthValue | HeightValue));
371 }
372 else if (frame_flags & (WidthValue | HeightValue))
373 {
374 w = frame_w; h = frame_h;
375 flags |= (frame_flags & (WidthValue | HeightValue));
376 }
377
378 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
379 if (!ew->emacs_frame.iconic)
380 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
381
382 first_frame_p = False;
383 }
384 else
385 {
386 /* If this is not the first frame created:
387 ========================================
388
389 - use the EmacsFrame's size/position if specified
390 - Otherwise, use the ApplicationShell's size, but not position.
391
392 So that means that one can specify the position of the first frame
393 with "Emacs.geometry" or `-geometry'; but can only specify the
394 position of subsequent frames with "*Frame-NAME.geometry".
395
396 AppShell comes second so that -geometry does not apply to subsequent
397 frames when there is an "every frame" entry in the resource db,
398 but does apply to the first frame.
399 */
400 if (frame_flags & (XValue | YValue))
401 {
402 x = frame_x; y = frame_y;
403 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
404 }
405
406 if (frame_flags & (WidthValue | HeightValue))
407 {
408 w = frame_w; h = frame_h;
409 flags |= (frame_flags & (WidthValue | HeightValue));
410 }
411 else if (app_flags & (WidthValue | HeightValue))
412 {
413 w = app_w;
414 h = app_h;
415 flags |= (app_flags & (WidthValue | HeightValue));
416 }
417 }
edaf359b 418#endif /* 0 */
07bf635f
RS
419 {
420 struct frame* frame = ew->emacs_frame.frame;
421 Dimension pixel_width, pixel_height;
422 char shell_position [32];
423
424 /* Take into account the size of the scrollbar */
425 frame->display.x->vertical_scroll_bar_extra
426 = (FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
427 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (frame)
428 : 0);
429
430
431 change_frame_size (frame, h, w, 1, 0);
432 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
433 ew->core.width = pixel_width;
434 ew->core.height = pixel_height;
435
edaf359b 436#if 0 /* We don't need this also. */
07bf635f
RS
437 /* If a position was specified, assign it to the shell widget.
438 (Else WM won't do anything with it.)
439 */
440 if (flags & (XValue | YValue))
441 {
442 /* the tricky things with the sign is to make sure that
443 -0 is printed -0. */
444 int len;
445 char *tem;
446 sprintf (shell_position, "=%c%d%c%d",
447 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
448 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
449 len = strlen (shell_position) + 1;
450 tem = (char *) xmalloc (len);
451 strncpy (tem, shell_position, len);
452 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
453 }
454 else if (flags & (WidthValue | HeightValue))
455 {
456 int len;
457 char *tem;
458 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
459 len = strlen (shell_position) + 1;
460 tem = (char *) xmalloc (len);
461 strncpy (tem, shell_position, len);
462 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
463 }
464
465 /* If the geometry spec we're using has W/H components, mark the size
466 in the WM_SIZE_HINTS as user specified. */
467 if (flags & (WidthValue | HeightValue))
468 mark_shell_size_user_specified (wmshell);
469
470 /* Also assign the iconic status of the frame to the Shell, so that
471 the WM sees it. */
472 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
edaf359b 473#endif /* 0 */
07bf635f
RS
474 }
475}
476
477
478static void
345a94f9
RS
479update_wm_hints (ew)
480 EmacsFrame ew;
07bf635f
RS
481{
482 Widget wmshell = get_wm_shell ((Widget)ew);
483 int cw;
484 int ch;
485 Dimension rounded_width;
486 Dimension rounded_height;
487 int char_width;
488 int char_height;
489 int base_width;
490 int base_height;
491 int min_rows = 0, min_cols = 0;
492
493 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
494
495 pixel_to_char_size (ew, ew->core.width, ew->core.height,
496 &char_width, &char_height);
497 char_to_pixel_size (ew, char_width, char_height,
498 &rounded_width, &rounded_height);
499 get_default_char_pixel_size (ew, &cw, &ch);
500
501 base_width = (wmshell->core.width - ew->core.width
502 + (rounded_width - (char_width * cw)));
503 base_height = (wmshell->core.height - ew->core.height
504 + (rounded_height - (char_height * ch)));
505
506 /* This is kind of sleazy, but I can't see how else to tell it to
507 make it mark the WM_SIZE_HINTS size as user specified.
508 */
509/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
510
511 XtVaSetValues (wmshell,
512 XtNbaseWidth, base_width,
513 XtNbaseHeight, base_height,
514 XtNwidthInc, cw,
515 XtNheightInc, ch,
516 XtNminWidth, base_width + min_cols * cw,
517 XtNminHeight, base_height + min_rows * ch,
518 0);
519}
520
521static void
345a94f9
RS
522create_frame_gcs (ew)
523 EmacsFrame ew;
07bf635f
RS
524{
525 struct frame* s = ew->emacs_frame.frame;
526
527 s->display.x->normal_gc =
528 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
529 s->display.x->reverse_gc =
530 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
531 s->display.x->cursor_gc =
532 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
533}
534
535static void
345a94f9
RS
536setup_frame_gcs (ew)
537 EmacsFrame ew;
07bf635f
RS
538{
539 XGCValues gc_values;
540 struct frame* s = ew->emacs_frame.frame;
541 Pixmap blank_stipple, blank_tile;
542
543 static char cursor_bits[] =
544 {
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
549 };
550
551 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
552 XGetGCValues returns uninitialized data when we query the stipple
553 (instead of None or something sensible) and it makes things hard.
554
555 This should be fixed for real by not querying the GCs but instead having
556 some GC-based cache instead of the current face-based cache which doesn't
557 effectively cache all of the GC settings we need to use.
558 */
559
560 blank_stipple =
561 XCreateBitmapFromData (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
562 cursor_bits, 2, 2);
563
564 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
565 never actually get used as a background tile!
566 */
567 blank_tile =
568 XCreatePixmapFromBitmapData (XtDisplay(ew),
569 RootWindowOfScreen (XtScreen (ew)),
570 cursor_bits, 2, 2, 0, 1, ew->core.depth);
571
572 /* Normal video */
573 gc_values.font = ew->emacs_frame.font->fid;
574 gc_values.foreground = ew->emacs_frame.foreground_pixel;
575 gc_values.background = ew->core.background_pixel;
576 gc_values.graphics_exposures = False;
577 gc_values.stipple = blank_stipple;
578 gc_values.tile = blank_tile;
579 XChangeGC (XtDisplay (ew), s->display.x->normal_gc,
580 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
581 | GCStipple | GCTile),
582 &gc_values);
583
584 /* Reverse video style. */
585 gc_values.font = ew->emacs_frame.font->fid;
586 gc_values.foreground = ew->core.background_pixel;
587 gc_values.background = ew->emacs_frame.foreground_pixel;
588 gc_values.graphics_exposures = False;
589 gc_values.stipple = blank_stipple;
590 gc_values.tile = blank_tile;
591 XChangeGC (XtDisplay (ew), s->display.x->reverse_gc,
592 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
593 | GCStipple | GCTile),
594 &gc_values);
595
596 /* Cursor has to have an empty stipple. */
597 gc_values.font = ew->emacs_frame.font->fid;
598 gc_values.foreground = ew->core.background_pixel;
599 gc_values.background = ew->emacs_frame.cursor_color;
600 gc_values.graphics_exposures = False;
601 gc_values.tile = blank_tile;
602 gc_values.stipple =
603 XCreateBitmapFromData (XtDisplay (ew),
604 RootWindowOfScreen (XtScreen (ew)),
605 cursor_bits, 16, 16);
606 XChangeGC (XtDisplay (ew), s->display.x->cursor_gc,
607 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
608 | GCStipple | GCTile),
609 &gc_values);
610}
611
612static void
345a94f9
RS
613update_various_frame_slots (ew)
614 EmacsFrame ew;
07bf635f
RS
615{
616 struct x_display* x = ew->emacs_frame.frame->display.x;
617 x->pixel_height = ew->core.height;
618 x->pixel_width = ew->core.width;
619 x->internal_border_width = ew->emacs_frame.internal_border_width;
620
621}
622
623static void
345a94f9
RS
624update_from_various_frame_slots (ew)
625 EmacsFrame ew;
07bf635f
RS
626{
627 struct x_display* x = ew->emacs_frame.frame->display.x;
628 ew->core.height = x->pixel_height;
629 ew->core.width = x->pixel_width;
630 ew->core.background_pixel = x->background_pixel;
631 ew->emacs_frame.internal_border_width = x->internal_border_width;
632 ew->emacs_frame.font = x->font;
633 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
634 ew->emacs_frame.cursor_color = x->cursor_pixel;
635 ew->core.border_pixel = x->border_pixel;
636}
637
638static void
345a94f9
RS
639EmacsFrameInitialize (request, new, dum1, dum2)
640 Widget request;
641 Widget new;
642 ArgList dum1;
643 Cardinal *dum2;
07bf635f
RS
644{
645 EmacsFrame ew = (EmacsFrame)new;
646
647 if (!ew->emacs_frame.frame)
648 {
649 fprintf (stderr,
650 "can't create an emacs frame widget without a frame\n");
651 exit (1);
652 }
653
654#if 0 /* done in xfns.c */
655 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
656 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
657 It's unfortunate that we have to do this, but we need to know the font
658 size for frame-sizing purposes before the faces get initialized. If
659 the "default.attributeFont" isn't set, then we use the font of this
660 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
661 the "default" face will use the frame's font if its own is not set,
662 so everything stays in sync -- it's not possible for the frame's font
663 and the default face's font to be different.
664 */
665 {
666 XFontStruct *f = 0;
667 XtResource face_res;
668 face_res.resource_name = "attributeFont";
669 face_res.resource_class = "AttributeFont";
670 face_res.resource_type = XtRFontStruct;
671 face_res.resource_size = sizeof (XFontStruct *);
672 face_res.resource_offset = 0;
673 face_res.default_type = XtRImmediate;
674 face_res.default_addr = 0;
675 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
676 &face_res, 1, NULL, 0);
677
678 if (f)
679 ew->emacs_frame.font = f;
680 else if (! ew->emacs_frame.font)
681 {
682 fprintf (stderr, "emacs frame widget could not load a font\n");
683 exit (1);
684 }
685 }
686
687/* Update the font field in frame */
688 ew->emacs_frame.frame->display.x->font = ew->emacs_frame.font;
689#endif
690
691 update_from_various_frame_slots (ew);
692 set_frame_size (ew);
693/*create_frame_gcs (ew);
694 setup_frame_gcs (ew);
695 update_various_frame_slots (ew); */
696}
697
698
699static void
345a94f9
RS
700EmacsFrameRealize (widget, mask, attrs)
701 Widget widget;
702 XtValueMask *mask;
703 XSetWindowAttributes *attrs;
07bf635f
RS
704{
705 EmacsFrame ew = (EmacsFrame)widget;
706
707 attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
708 ButtonReleaseMask | StructureNotifyMask |
709 FocusChangeMask | PointerMotionHintMask |
710 PointerMotionMask | LeaveWindowMask | EnterWindowMask |
711 VisibilityChangeMask | PropertyChangeMask |
712 StructureNotifyMask | SubstructureNotifyMask |
713 SubstructureRedirectMask);
714 *mask |= CWEventMask;
715 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
716 attrs);
717 update_wm_hints (ew);
718}
719
345a94f9 720extern void free_frame_faces (/* struct frame * */);
07bf635f
RS
721
722static void
345a94f9
RS
723EmacsFrameDestroy (widget)
724 Widget widget;
07bf635f
RS
725{
726 EmacsFrame ew = (EmacsFrame) widget;
727 struct frame* s = ew->emacs_frame.frame;
728
729 if (! s) abort ();
730 if (! s->display.x) abort ();
731 if (! s->display.x->normal_gc) abort ();
732
733 /* this would be called from Fdelete_frame() but it needs to free some
734 stuff after the widget has been finalized but before the widget has
735 been freed. */
736 free_frame_faces (s);
737
738 /* need to be careful that the face-freeing code doesn't free these too */
739 XFreeGC (XtDisplay (widget), s->display.x->normal_gc);
740 XFreeGC (XtDisplay (widget), s->display.x->reverse_gc);
741 XFreeGC (XtDisplay (widget), s->display.x->cursor_gc);
742}
743
744void
345a94f9
RS
745EmacsFrameResize (widget)
746 Widget widget;
07bf635f
RS
747{
748 EmacsFrame ew = (EmacsFrame)widget;
749 struct frame *f = ew->emacs_frame.frame;
750 int columns;
751 int rows;
752
753 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
754 change_frame_size (f, rows, columns, 1, 0);
755 update_wm_hints (ew);
07bf635f
RS
756 update_various_frame_slots (ew);
757}
758
759static Boolean
345a94f9
RS
760EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
761 Widget cur_widget;
762 Widget req_widget;
763 Widget new_widget;
764 ArgList dum1;
765 Cardinal *dum2;
07bf635f
RS
766{
767 EmacsFrame cur = (EmacsFrame)cur_widget;
768 EmacsFrame new = (EmacsFrame)new_widget;
769
770 Boolean needs_a_refresh = False;
771 Boolean has_to_recompute_size;
772 Boolean has_to_recompute_gcs;
773 Boolean has_to_update_hints;
774
775 int char_width, char_height;
776 Dimension pixel_width;
777 Dimension pixel_height;
778
779 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
780 || (cur->emacs_frame.foreground_pixel
781 != new->emacs_frame.foreground_pixel)
782 || (cur->core.background_pixel
783 != new->core.background_pixel)
784 );
785
786 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
787 && cur->core.width == new->core.width
788 && cur->core.height == new->core.height);
789
790 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
791
792 if (has_to_recompute_gcs)
793 {
794 setup_frame_gcs (new);
795 needs_a_refresh = True;
796 }
797
798 if (has_to_recompute_size)
799 {
800 pixel_width = new->core.width;
801 pixel_height = new->core.height;
802 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
803 &char_height);
804 char_to_pixel_size (new, char_width, char_height, &pixel_width,
805 &pixel_height);
806 new->core.width = pixel_width;
807 new->core.height = pixel_height;
808
809 change_frame_size (new->emacs_frame.frame, char_height, char_width,
810 1, 0);
811 needs_a_refresh = True;
812 }
813
814 if (has_to_update_hints)
815 update_wm_hints (new);
816
817 update_various_frame_slots (new);
818
819 /* #### This doesn't work, I haven't been able to find ANY kludge that
820 will let (x-create-frame '((iconic . t))) work. It seems that changes
821 to wm_shell's iconic slot have no effect after it has been realized,
822 and calling XIconifyWindow doesn't work either (even thought the window
823 has been created.) Perhaps there is some property we could smash
824 directly, but I'm sick of this for now. Xt is a steaming pile of shit!
825 */
826 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
827 {
828 Widget wmshell = get_wm_shell ((Widget) cur);
829 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
830 }
831
832 return needs_a_refresh;
833}
834
835static XtGeometryResult
345a94f9
RS
836EmacsFrameQueryGeometry (widget, request, result)
837 Widget widget;
838 XtWidgetGeometry* request;
839 XtWidgetGeometry* result;
07bf635f
RS
840{
841 EmacsFrame ew = (EmacsFrame)widget;
842
843 int mask = request->request_mode;
844 Dimension ok_width, ok_height;
845
846 if (mask & (CWWidth | CWHeight))
847 {
848 round_size_to_char (ew,
849 (mask & CWWidth) ? request->width : ew->core.width,
850 ((mask & CWHeight) ? request->height
851 : ew->core.height),
852 &ok_width, &ok_height);
853 if ((mask & CWWidth) && (ok_width != request->width))
854 {
855 result->request_mode |= CWWidth;
856 result->width = ok_width;
857 }
858 if ((mask & CWHeight) && (ok_height != request->height))
859 {
860 result->request_mode |= CWHeight;
861 result->height = ok_height;
862 }
863 }
864 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
865}
866
07bf635f
RS
867/* Special entrypoints */
868void
345a94f9
RS
869EmacsFrameSetCharSize (widget, columns, rows)
870 Widget widget;
871 int columns;
872 int rows;
07bf635f
RS
873{
874 EmacsFrame ew = (EmacsFrame) widget;
875 Dimension pixel_width, pixel_height, granted_width, granted_height;
876 XtGeometryResult result;
982a94d9 877 struct frame *f = ew->emacs_frame.frame;
b3ccf2a2
FP
878 Arg al[2];
879 int ac = 0;
880
07bf635f
RS
881 if (columns < 3) columns = 3; /* no way buddy */
882 if (rows < 3) rows = 3;
883
a9e3d212
FP
884 f->display.x->left_pos = f->display.x->widget->core.x;
885 f->display.x->top_pos = f->display.x->widget->core.y;
886
982a94d9
FP
887 check_frame_size (f, &rows, &columns);
888 f->display.x->vertical_scroll_bar_extra
889 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
890 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
891 : 0);
07bf635f 892 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
57aa60d8 893
57aa60d8
FP
894 /* Recompute the entire geometry management. */
895 if (ew->core.width != pixel_width || ew->core.height != pixel_height)
07bf635f 896 {
57aa60d8
FP
897 int hdelta = pixel_height - ew->core.height;
898 int column_widget_height = f->display.x->column_widget->core.height;
e5c001e3
FP
899 XawPanedSetRefigureMode (f->display.x->column_widget, False);
900
b3ccf2a2 901 ac = 0;
e5c001e3
FP
902 XtSetArg (al[ac], XtNheight, pixel_height); ac++;
903 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
904 XtSetValues ((Widget) ew, al, ac);
b3ccf2a2
FP
905
906 ac = 0;
907 XtSetArg (al[ac], XtNheight, column_widget_height + hdelta); ac++;
908 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
909 XtSetValues (f->display.x->column_widget, al, ac);
910
e5c001e3 911 XawPanedSetRefigureMode (f->display.x->column_widget, True);
07bf635f 912 }
982a94d9
FP
913
914 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
915 receive in the ConfigureNotify event; if we get what we asked
916 for, then the event won't cause the screen to become garbaged, so
917 we have to make sure to do it here. */
918 SET_FRAME_GARBAGED (f);
47d53175
FP
919
920 /* Coordinates of the toplevel widget seem to have been lost.
921 So set it to the rignt values. */
b3ccf2a2
FP
922 ac = 0;
923 XtSetArg (al[ac], XtNx, f->display.x->left_pos); ac++;
924 XtSetArg (al[ac], XtNy, f->display.x->top_pos); ac++;
925 XtSetValues (f->display.x->widget, al, ac);
07bf635f 926}