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