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