(lwlib_toolkit_type): New variable.
[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
9e65ad77 22#include <config.h>
565620a5 23#include <stdio.h>
07bf635f
RS
24#include "lisp.h"
25#include "xterm.h"
26
27#include "frame.h"
28
29#include "dispextern.h"
49fe12a9 30#include "blockinput.h"
07bf635f
RS
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>
69524b98 39#include "../lwlib/lwlib.h"
07bf635f
RS
40
41#define max(a, b) ((a) > (b) ? (a) : (b))
42
43/* This sucks: this is the first default that x-faces.el tries. This won't
44 be used unless neither the "Emacs.EmacsFrame" resource nor the
45 "Emacs.EmacsFrame" resource is set; the frame
46 may have the wrong default size if this font doesn't exist, but some other
47 font that x-faces.el does. The workaround is to specify some font in the
48 resource database; I don't know a solution other than duplicating the font-
49 searching code from x-faces.el in this file.
50
51 This also means that if "Emacs.EmacsFrame" is specified as a non-
52 existent font, then Xt is going to substitute "XtDefaultFont" for it,
53 which is a different size than this one. The solution for this is to
54 make x-faces.el try to use XtDefaultFont. The problem with that is that
55 XtDefaultFont is almost certainly variable-width.
56
57 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
58 */
59#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
60
61
01492d1b
RS
62static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
63static void EmacsFrameDestroy (/* Widget */);
64static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
65void EmacsFrameResize (/* Widget widget */);
66static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
67 ArgList, Cardinal * */);
68static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
69 XtWidgetGeometry* */);
07bf635f
RS
70
71
72#undef XtOffset
73#define XtOffset(p_type,field) \
74 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
75#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
76
77static XtResource resources[] = {
78 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
79 offset (geometry), XtRString, (XtPointer) 0},
80 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
81 offset (iconic), XtRImmediate, (XtPointer) False},
82
83 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
84 offset (frame), XtRImmediate, 0},
85
86 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
87 offset (minibuffer), XtRImmediate, (XtPointer)0},
88 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
89 offset (unsplittable), XtRImmediate, (XtPointer)0},
90 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
91 offset (internal_border_width), XtRImmediate, (XtPointer)4},
92 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
93 offset (interline), XtRImmediate, (XtPointer)0},
94 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
95 offset(font),XtRString, DEFAULT_FACE_FONT},
96 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
97 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
98 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
99 offset(cursor_color), XtRString, "XtDefaultForeground"},
100 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
101 offset (bar_cursor), XtRImmediate, (XtPointer)0},
102 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
103 offset (visual_bell), XtRImmediate, (XtPointer)0},
104 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
105 offset (bell_volume), XtRImmediate, (XtPointer)0},
106};
107
108#undef offset
109
110/*
111static XtActionsRec
112emacsFrameActionsTable [] = {
113 {"keypress", key_press},
114 {"focus_in", emacs_frame_focus_handler},
115 {"focus_out", emacs_frame_focus_handler},
116};
117
118static char
119emacsFrameTranslations [] = "\
120<KeyPress>: keypress()\n\
121<FocusIn>: focus_in()\n\
122<FocusOut>: focus_out()\n\
123";
124*/
125
126EmacsFrameClassRec emacsFrameClassRec = {
127 { /* core fields */
128 /* superclass */ &widgetClassRec,
129 /* class_name */ "EmacsFrame",
130 /* widget_size */ sizeof(EmacsFrameRec),
131 /* class_initialize */ 0,
132 /* class_part_initialize */ 0,
133 /* class_inited */ FALSE,
134 /* initialize */ EmacsFrameInitialize,
135 /* initialize_hook */ 0,
136 /* realize */ EmacsFrameRealize,
137 /* actions */ 0, /*emacsFrameActionsTable*/
138 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
139 /* resources */ resources,
140 /* resource_count */ XtNumber(resources),
141 /* xrm_class */ NULLQUARK,
142 /* compress_motion */ TRUE,
143 /* compress_exposure */ TRUE,
144 /* compress_enterleave */ TRUE,
145 /* visible_interest */ FALSE,
146 /* destroy */ EmacsFrameDestroy,
147 /* resize */ EmacsFrameResize,
148 /* expose */ XtInheritExpose,
149 /* set_values */ EmacsFrameSetValues,
150 /* set_values_hook */ 0,
151 /* set_values_almost */ XtInheritSetValuesAlmost,
152 /* get_values_hook */ 0,
153 /* accept_focus */ XtInheritAcceptFocus,
154 /* version */ XtVersion,
155 /* callback_private */ 0,
156 /* tm_table */ 0, /*emacsFrameTranslations*/
157 /* query_geometry */ EmacsFrameQueryGeometry,
158 /* display_accelerator */ XtInheritDisplayAccelerator,
159 /* extension */ 0
160 }
161};
162
163WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
164
165static void
01492d1b
RS
166get_default_char_pixel_size (ew, pixel_width, pixel_height)
167 EmacsFrame ew;
168 int* pixel_width;
169 int* pixel_height;
07bf635f 170{
07bf635f
RS
171 struct frame* f = ew->emacs_frame.frame;
172 *pixel_width = FONT_WIDTH (f->display.x->font);
34216706 173 *pixel_height = f->display.x->line_height;
07bf635f
RS
174}
175
176static void
01492d1b
RS
177pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
178 EmacsFrame ew;
179 Dimension pixel_width;
180 Dimension pixel_height;
181 int* char_width;
182 int* char_height;
07bf635f
RS
183{
184 struct frame* f = ew->emacs_frame.frame;
185 *char_width = PIXEL_TO_CHAR_WIDTH (f, pixel_width);
186 *char_height = PIXEL_TO_CHAR_HEIGHT (f, pixel_height);
187}
188
189static void
345a94f9
RS
190char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
191 EmacsFrame ew;
192 int char_width;
193 int char_height;
194 Dimension* pixel_width;
195 Dimension* pixel_height;
07bf635f
RS
196{
197 struct frame* f = ew->emacs_frame.frame;
198 *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
199 *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
200}
201
202static void
345a94f9
RS
203round_size_to_char (ew, in_width, in_height, out_width, out_height)
204 EmacsFrame ew;
205 Dimension in_width;
206 Dimension in_height;
207 Dimension* out_width;
208 Dimension* out_height;
07bf635f
RS
209{
210 int char_width;
211 int char_height;
212 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
213 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
214}
215
216static Widget
345a94f9
RS
217get_wm_shell (w)
218 Widget w;
07bf635f
RS
219{
220 Widget wmshell;
221
222 for (wmshell = XtParent (w);
223 wmshell && !XtIsWMShell (wmshell);
224 wmshell = XtParent (wmshell));
225
226 return wmshell;
227}
228
229static void
345a94f9
RS
230mark_shell_size_user_specified (wmshell)
231 Widget wmshell;
07bf635f
RS
232{
233 if (! XtIsWMShell (wmshell)) abort ();
234 /* This is kind of sleazy, but I can't see how else to tell it to make it
235 mark the WM_SIZE_HINTS size as user specified when appropriate. */
236 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
237}
238
239
240/* Can't have static frame locals because of some broken compilers.
241 Normally, initializing a variable like this doesn't work in emacs,
242 but it's ok in this file because it must come after lastfile (and
243 thus have its data not go into text space) because Xt needs to
244 write to initialized data objects too.
245 */
246static Boolean first_frame_p = True;
247
248static void
345a94f9
RS
249set_frame_size (ew)
250 EmacsFrame ew;
07bf635f
RS
251{
252 /* The widget hierarchy is
253
254 argv[0] emacsShell pane Frame-NAME
255 ApplicationShell EmacsShell Paned EmacsFrame
256
257 We accept geometry specs in this order:
258
259 *Frame-NAME.geometry
260 *EmacsFrame.geometry
261 Emacs.geometry
262
263 Other possibilities for widget hierarchies might be
264
265 argv[0] frame pane Frame-NAME
266 ApplicationShell EmacsShell Paned EmacsFrame
267 or
268 argv[0] Frame-NAME pane Frame-NAME
269 ApplicationShell EmacsShell Paned EmacsFrame
270 or
271 argv[0] Frame-NAME pane emacsTextPane
272 ApplicationShell EmacsFrame Paned EmacsTextPane
273
274 With the current setup, the text-display-area is the part which is
275 an emacs "frame", since that's the only part managed by emacs proper
276 (the menubar and the parent of the menubar and all that sort of thing
277 are managed by lwlib.)
278
279 The EmacsShell widget is simply a replacement for the Shell widget
280 which is able to deal with using an externally-supplied window instead
281 of always creating its own. It is not actually emacs specific, and
282 should possibly have class "Shell" instead of "EmacsShell" to simplify
283 the resources.
284
285 */
286
287 /* Geometry of the AppShell */
288 int app_flags = 0;
289 int app_x = 0;
290 int app_y = 0;
291 unsigned int app_w = 0;
292 unsigned int app_h = 0;
293
294 /* Geometry of the EmacsFrame */
295 int frame_flags = 0;
296 int frame_x = 0;
297 int frame_y = 0;
298 unsigned int frame_w = 0;
299 unsigned int frame_h = 0;
300
301 /* Hairily merged geometry */
302 int x = 0;
303 int y = 0;
304 unsigned int w = ew->emacs_frame.frame->width;
305 unsigned int h = ew->emacs_frame.frame->height;
306 int flags = 0;
307
308 Widget wmshell = get_wm_shell ((Widget) ew);
38971c41
RS
309 /* Each Emacs shell is now independent and top-level. */
310 Widget app_shell = wmshell;
07bf635f 311
07bf635f 312 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
07bf635f 313
edaf359b
FP
314 /* We don't need this for the momment. The geometry is computed in
315 xfns.c. */
316#if 0
07bf635f
RS
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, 0);
322
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, 0);
327
328
329 {
330 char *geom = 0;
331 XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
332 if (geom)
333 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
334 }
335
336 if (ew->emacs_frame.geometry)
337 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
338 &frame_x, &frame_y,
339 &frame_w, &frame_h);
340
341 if (first_frame_p)
342 {
343 /* If this is the first frame created:
344 ====================================
345
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")
350
351 - If the AppShell is iconic, the frame should be iconic.
352
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.
356 */
357 if (app_flags & (XValue | YValue))
358 {
359 x = app_x; y = app_y;
360 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
361 }
362 else if (frame_flags & (XValue | YValue))
363 {
364 x = frame_x; y = frame_y;
365 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
366 }
367
368 if (app_flags & (WidthValue | HeightValue))
369 {
370 w = app_w; h = app_h;
371 flags |= (app_flags & (WidthValue | HeightValue));
372 }
373 else if (frame_flags & (WidthValue | HeightValue))
374 {
375 w = frame_w; h = frame_h;
376 flags |= (frame_flags & (WidthValue | HeightValue));
377 }
378
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, 0);
382
383 first_frame_p = False;
384 }
385 else
386 {
387 /* If this is not the first frame created:
388 ========================================
389
390 - use the EmacsFrame's size/position if specified
391 - Otherwise, use the ApplicationShell's size, but not position.
392
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".
396
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.
400 */
401 if (frame_flags & (XValue | YValue))
402 {
403 x = frame_x; y = frame_y;
404 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
405 }
406
407 if (frame_flags & (WidthValue | HeightValue))
408 {
409 w = frame_w; h = frame_h;
410 flags |= (frame_flags & (WidthValue | HeightValue));
411 }
412 else if (app_flags & (WidthValue | HeightValue))
413 {
414 w = app_w;
415 h = app_h;
416 flags |= (app_flags & (WidthValue | HeightValue));
417 }
418 }
edaf359b 419#endif /* 0 */
07bf635f
RS
420 {
421 struct frame* frame = ew->emacs_frame.frame;
422 Dimension pixel_width, pixel_height;
423 char shell_position [32];
424
425 /* Take into account the size of the scrollbar */
426 frame->display.x->vertical_scroll_bar_extra
02a162bf
KH
427 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
428 ? 0
429 : FRAME_SCROLL_BAR_PIXEL_WIDTH (frame) > 0
cb642304 430 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (frame)
02a162bf
KH
431 : (FRAME_SCROLL_BAR_COLS (frame)
432 * FONT_WIDTH (frame->display.x->font)));
07bf635f
RS
433
434 change_frame_size (frame, h, w, 1, 0);
435 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
436 ew->core.width = pixel_width;
437 ew->core.height = pixel_height;
438
6ae9a3f2 439#if 0 /* xfns.c takes care of this now. */
07bf635f
RS
440 /* If a position was specified, assign it to the shell widget.
441 (Else WM won't do anything with it.)
442 */
443 if (flags & (XValue | YValue))
444 {
445 /* the tricky things with the sign is to make sure that
446 -0 is printed -0. */
447 int len;
448 char *tem;
449 sprintf (shell_position, "=%c%d%c%d",
450 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
451 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
452 len = strlen (shell_position) + 1;
453 tem = (char *) xmalloc (len);
454 strncpy (tem, shell_position, len);
455 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
456 }
457 else if (flags & (WidthValue | HeightValue))
458 {
459 int len;
460 char *tem;
461 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
462 len = strlen (shell_position) + 1;
463 tem = (char *) xmalloc (len);
464 strncpy (tem, shell_position, len);
465 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
466 }
467
468 /* If the geometry spec we're using has W/H components, mark the size
469 in the WM_SIZE_HINTS as user specified. */
470 if (flags & (WidthValue | HeightValue))
471 mark_shell_size_user_specified (wmshell);
472
473 /* Also assign the iconic status of the frame to the Shell, so that
474 the WM sees it. */
475 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
edaf359b 476#endif /* 0 */
07bf635f
RS
477 }
478}
479
480
481static void
345a94f9
RS
482update_wm_hints (ew)
483 EmacsFrame ew;
07bf635f
RS
484{
485 Widget wmshell = get_wm_shell ((Widget)ew);
486 int cw;
487 int ch;
488 Dimension rounded_width;
489 Dimension rounded_height;
490 int char_width;
491 int char_height;
492 int base_width;
493 int base_height;
494 int min_rows = 0, min_cols = 0;
495
496 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
497
498 pixel_to_char_size (ew, ew->core.width, ew->core.height,
499 &char_width, &char_height);
500 char_to_pixel_size (ew, char_width, char_height,
501 &rounded_width, &rounded_height);
502 get_default_char_pixel_size (ew, &cw, &ch);
503
504 base_width = (wmshell->core.width - ew->core.width
505 + (rounded_width - (char_width * cw)));
506 base_height = (wmshell->core.height - ew->core.height
507 + (rounded_height - (char_height * ch)));
508
509 /* This is kind of sleazy, but I can't see how else to tell it to
510 make it mark the WM_SIZE_HINTS size as user specified.
511 */
512/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
513
514 XtVaSetValues (wmshell,
515 XtNbaseWidth, base_width,
516 XtNbaseHeight, base_height,
517 XtNwidthInc, cw,
518 XtNheightInc, ch,
519 XtNminWidth, base_width + min_cols * cw,
520 XtNminHeight, base_height + min_rows * ch,
521 0);
522}
523
524static void
345a94f9
RS
525create_frame_gcs (ew)
526 EmacsFrame ew;
07bf635f 527{
7f18598b 528 struct frame *s = ew->emacs_frame.frame;
07bf635f 529
85e53327
KH
530 s->display.x->normal_gc
531 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
532 (unsigned long)0, (XGCValues *)0);
533 s->display.x->reverse_gc
534 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
535 (unsigned long)0, (XGCValues *)0);
536 s->display.x->cursor_gc
537 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
538 (unsigned long)0, (XGCValues *)0);
07bf635f
RS
539}
540
1ad2277b
RS
541static char setup_frame_cursor_bits[] =
542{
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
547};
548
07bf635f 549static void
345a94f9
RS
550setup_frame_gcs (ew)
551 EmacsFrame ew;
07bf635f
RS
552{
553 XGCValues gc_values;
554 struct frame* s = ew->emacs_frame.frame;
555 Pixmap blank_stipple, blank_tile;
556
07bf635f
RS
557 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
558 XGetGCValues returns uninitialized data when we query the stipple
559 (instead of None or something sensible) and it makes things hard.
560
561 This should be fixed for real by not querying the GCs but instead having
562 some GC-based cache instead of the current face-based cache which doesn't
563 effectively cache all of the GC settings we need to use.
564 */
565
85e53327
KH
566 blank_stipple
567 = XCreateBitmapFromData (XtDisplay (ew),
568 RootWindowOfScreen (XtScreen (ew)),
569 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
570
571 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
572 never actually get used as a background tile!
573 */
85e53327
KH
574 blank_tile
575 = XCreatePixmapFromBitmapData (XtDisplay(ew),
576 RootWindowOfScreen (XtScreen (ew)),
577 setup_frame_cursor_bits, 2, 2,
578 (unsigned long)0, (unsigned long)1,
579 ew->core.depth);
07bf635f
RS
580
581 /* Normal video */
582 gc_values.font = ew->emacs_frame.font->fid;
583 gc_values.foreground = ew->emacs_frame.foreground_pixel;
584 gc_values.background = ew->core.background_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->normal_gc,
589 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
590 | GCStipple | GCTile),
591 &gc_values);
592
593 /* Reverse video style. */
594 gc_values.font = ew->emacs_frame.font->fid;
595 gc_values.foreground = ew->core.background_pixel;
596 gc_values.background = ew->emacs_frame.foreground_pixel;
597 gc_values.graphics_exposures = False;
598 gc_values.stipple = blank_stipple;
599 gc_values.tile = blank_tile;
600 XChangeGC (XtDisplay (ew), s->display.x->reverse_gc,
601 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
602 | GCStipple | GCTile),
603 &gc_values);
604
605 /* Cursor has to have an empty stipple. */
606 gc_values.font = ew->emacs_frame.font->fid;
607 gc_values.foreground = ew->core.background_pixel;
608 gc_values.background = ew->emacs_frame.cursor_color;
609 gc_values.graphics_exposures = False;
610 gc_values.tile = blank_tile;
85e53327
KH
611 gc_values.stipple
612 = XCreateBitmapFromData (XtDisplay (ew),
613 RootWindowOfScreen (XtScreen (ew)),
614 setup_frame_cursor_bits, 16, 16);
07bf635f
RS
615 XChangeGC (XtDisplay (ew), s->display.x->cursor_gc,
616 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
617 | GCStipple | GCTile),
618 &gc_values);
619}
620
621static void
345a94f9
RS
622update_various_frame_slots (ew)
623 EmacsFrame ew;
07bf635f
RS
624{
625 struct x_display* x = ew->emacs_frame.frame->display.x;
626 x->pixel_height = ew->core.height;
627 x->pixel_width = ew->core.width;
628 x->internal_border_width = ew->emacs_frame.internal_border_width;
629
630}
631
632static void
345a94f9
RS
633update_from_various_frame_slots (ew)
634 EmacsFrame ew;
07bf635f
RS
635{
636 struct x_display* x = ew->emacs_frame.frame->display.x;
637 ew->core.height = x->pixel_height;
638 ew->core.width = x->pixel_width;
639 ew->core.background_pixel = x->background_pixel;
640 ew->emacs_frame.internal_border_width = x->internal_border_width;
641 ew->emacs_frame.font = x->font;
642 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
643 ew->emacs_frame.cursor_color = x->cursor_pixel;
644 ew->core.border_pixel = x->border_pixel;
645}
646
647static void
345a94f9
RS
648EmacsFrameInitialize (request, new, dum1, dum2)
649 Widget request;
650 Widget new;
651 ArgList dum1;
652 Cardinal *dum2;
07bf635f
RS
653{
654 EmacsFrame ew = (EmacsFrame)new;
655
656 if (!ew->emacs_frame.frame)
657 {
658 fprintf (stderr,
659 "can't create an emacs frame widget without a frame\n");
660 exit (1);
661 }
662
663#if 0 /* done in xfns.c */
664 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
665 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
666 It's unfortunate that we have to do this, but we need to know the font
667 size for frame-sizing purposes before the faces get initialized. If
668 the "default.attributeFont" isn't set, then we use the font of this
669 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
670 the "default" face will use the frame's font if its own is not set,
671 so everything stays in sync -- it's not possible for the frame's font
672 and the default face's font to be different.
673 */
674 {
675 XFontStruct *f = 0;
676 XtResource face_res;
677 face_res.resource_name = "attributeFont";
678 face_res.resource_class = "AttributeFont";
679 face_res.resource_type = XtRFontStruct;
680 face_res.resource_size = sizeof (XFontStruct *);
681 face_res.resource_offset = 0;
682 face_res.default_type = XtRImmediate;
683 face_res.default_addr = 0;
684 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
685 &face_res, 1, NULL, 0);
686
687 if (f)
688 ew->emacs_frame.font = f;
689 else if (! ew->emacs_frame.font)
690 {
691 fprintf (stderr, "emacs frame widget could not load a font\n");
692 exit (1);
693 }
694 }
695
696/* Update the font field in frame */
697 ew->emacs_frame.frame->display.x->font = ew->emacs_frame.font;
698#endif
699
700 update_from_various_frame_slots (ew);
701 set_frame_size (ew);
702/*create_frame_gcs (ew);
703 setup_frame_gcs (ew);
704 update_various_frame_slots (ew); */
705}
706
707
708static void
345a94f9
RS
709EmacsFrameRealize (widget, mask, attrs)
710 Widget widget;
711 XtValueMask *mask;
712 XSetWindowAttributes *attrs;
07bf635f
RS
713{
714 EmacsFrame ew = (EmacsFrame)widget;
715
716 attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
717 ButtonReleaseMask | StructureNotifyMask |
718 FocusChangeMask | PointerMotionHintMask |
719 PointerMotionMask | LeaveWindowMask | EnterWindowMask |
720 VisibilityChangeMask | PropertyChangeMask |
721 StructureNotifyMask | SubstructureNotifyMask |
722 SubstructureRedirectMask);
723 *mask |= CWEventMask;
724 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
725 attrs);
726 update_wm_hints (ew);
727}
728
345a94f9 729extern void free_frame_faces (/* struct frame * */);
07bf635f
RS
730
731static void
345a94f9
RS
732EmacsFrameDestroy (widget)
733 Widget widget;
07bf635f
RS
734{
735 EmacsFrame ew = (EmacsFrame) widget;
736 struct frame* s = ew->emacs_frame.frame;
737
738 if (! s) abort ();
739 if (! s->display.x) abort ();
740 if (! s->display.x->normal_gc) abort ();
741
742 /* this would be called from Fdelete_frame() but it needs to free some
743 stuff after the widget has been finalized but before the widget has
744 been freed. */
745 free_frame_faces (s);
746
49fe12a9 747 BLOCK_INPUT;
07bf635f
RS
748 /* need to be careful that the face-freeing code doesn't free these too */
749 XFreeGC (XtDisplay (widget), s->display.x->normal_gc);
750 XFreeGC (XtDisplay (widget), s->display.x->reverse_gc);
751 XFreeGC (XtDisplay (widget), s->display.x->cursor_gc);
49fe12a9 752 UNBLOCK_INPUT;
07bf635f
RS
753}
754
755void
345a94f9
RS
756EmacsFrameResize (widget)
757 Widget widget;
07bf635f
RS
758{
759 EmacsFrame ew = (EmacsFrame)widget;
760 struct frame *f = ew->emacs_frame.frame;
761 int columns;
762 int rows;
763
764 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
765 change_frame_size (f, rows, columns, 1, 0);
766 update_wm_hints (ew);
07bf635f
RS
767 update_various_frame_slots (ew);
768}
769
770static Boolean
345a94f9
RS
771EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
772 Widget cur_widget;
773 Widget req_widget;
774 Widget new_widget;
775 ArgList dum1;
776 Cardinal *dum2;
07bf635f
RS
777{
778 EmacsFrame cur = (EmacsFrame)cur_widget;
779 EmacsFrame new = (EmacsFrame)new_widget;
780
781 Boolean needs_a_refresh = False;
782 Boolean has_to_recompute_size;
783 Boolean has_to_recompute_gcs;
784 Boolean has_to_update_hints;
785
786 int char_width, char_height;
787 Dimension pixel_width;
788 Dimension pixel_height;
789
790 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
791 || (cur->emacs_frame.foreground_pixel
792 != new->emacs_frame.foreground_pixel)
793 || (cur->core.background_pixel
794 != new->core.background_pixel)
795 );
796
797 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
798 && cur->core.width == new->core.width
799 && cur->core.height == new->core.height);
800
801 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
802
803 if (has_to_recompute_gcs)
804 {
805 setup_frame_gcs (new);
806 needs_a_refresh = True;
807 }
808
809 if (has_to_recompute_size)
810 {
811 pixel_width = new->core.width;
812 pixel_height = new->core.height;
813 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
814 &char_height);
815 char_to_pixel_size (new, char_width, char_height, &pixel_width,
816 &pixel_height);
817 new->core.width = pixel_width;
818 new->core.height = pixel_height;
819
820 change_frame_size (new->emacs_frame.frame, char_height, char_width,
821 1, 0);
822 needs_a_refresh = True;
823 }
824
825 if (has_to_update_hints)
826 update_wm_hints (new);
827
828 update_various_frame_slots (new);
829
830 /* #### This doesn't work, I haven't been able to find ANY kludge that
831 will let (x-create-frame '((iconic . t))) work. It seems that changes
832 to wm_shell's iconic slot have no effect after it has been realized,
833 and calling XIconifyWindow doesn't work either (even thought the window
834 has been created.) Perhaps there is some property we could smash
835 directly, but I'm sick of this for now. Xt is a steaming pile of shit!
836 */
837 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
838 {
839 Widget wmshell = get_wm_shell ((Widget) cur);
840 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
841 }
842
843 return needs_a_refresh;
844}
845
846static XtGeometryResult
345a94f9
RS
847EmacsFrameQueryGeometry (widget, request, result)
848 Widget widget;
849 XtWidgetGeometry* request;
850 XtWidgetGeometry* result;
07bf635f
RS
851{
852 EmacsFrame ew = (EmacsFrame)widget;
853
854 int mask = request->request_mode;
855 Dimension ok_width, ok_height;
856
857 if (mask & (CWWidth | CWHeight))
858 {
859 round_size_to_char (ew,
860 (mask & CWWidth) ? request->width : ew->core.width,
861 ((mask & CWHeight) ? request->height
862 : ew->core.height),
863 &ok_width, &ok_height);
864 if ((mask & CWWidth) && (ok_width != request->width))
865 {
866 result->request_mode |= CWWidth;
867 result->width = ok_width;
868 }
869 if ((mask & CWHeight) && (ok_height != request->height))
870 {
871 result->request_mode |= CWHeight;
872 result->height = ok_height;
873 }
874 }
875 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
876}
877
07bf635f
RS
878/* Special entrypoints */
879void
345a94f9
RS
880EmacsFrameSetCharSize (widget, columns, rows)
881 Widget widget;
882 int columns;
883 int rows;
07bf635f
RS
884{
885 EmacsFrame ew = (EmacsFrame) widget;
886 Dimension pixel_width, pixel_height, granted_width, granted_height;
887 XtGeometryResult result;
982a94d9 888 struct frame *f = ew->emacs_frame.frame;
b3ccf2a2
FP
889 Arg al[2];
890 int ac = 0;
891
07bf635f 892 if (columns < 3) columns = 3; /* no way buddy */
07bf635f 893
982a94d9
FP
894 check_frame_size (f, &rows, &columns);
895 f->display.x->vertical_scroll_bar_extra
02a162bf
KH
896 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
897 ? 0
898 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
cb642304 899 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
02a162bf
KH
900 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->display.x->font)));
901
07bf635f 902 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
57aa60d8 903
57aa60d8
FP
904 /* Recompute the entire geometry management. */
905 if (ew->core.width != pixel_width || ew->core.height != pixel_height)
07bf635f 906 {
57aa60d8
FP
907 int hdelta = pixel_height - ew->core.height;
908 int column_widget_height = f->display.x->column_widget->core.height;
50d5aeb5
RS
909 int old_left = f->display.x->widget->core.x;
910 int old_top = f->display.x->widget->core.y;
911
69524b98 912 lw_refigure_widget (f->display.x->column_widget, False);
b3ccf2a2 913 ac = 0;
e5c001e3
FP
914 XtSetArg (al[ac], XtNheight, pixel_height); ac++;
915 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
916 XtSetValues ((Widget) ew, al, ac);
b3ccf2a2
FP
917
918 ac = 0;
919 XtSetArg (al[ac], XtNheight, column_widget_height + hdelta); ac++;
920 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
921 XtSetValues (f->display.x->column_widget, al, ac);
69524b98 922 lw_refigure_widget (f->display.x->column_widget, True);
50d5aeb5
RS
923
924 /* These seem to get clobbered. I don't know why. - rms. */
925 f->display.x->widget->core.x = old_left;
926 f->display.x->widget->core.y = old_top;
07bf635f 927 }
982a94d9
FP
928
929 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
930 receive in the ConfigureNotify event; if we get what we asked
931 for, then the event won't cause the screen to become garbaged, so
932 we have to make sure to do it here. */
933 SET_FRAME_GARBAGED (f);
07bf635f 934}