Add arch taglines
[bpt/emacs.git] / src / widget.c
CommitLineData
07bf635f 1/* The emacs frame widget.
0dea0fed 2 Copyright (C) 1992, 1993, 2000 Free Software Foundation, Inc.
07bf635f
RS
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
87a43646 38#include "keyboard.h"
07bf635f 39#include "frame.h"
dfcf069d 40#include "window.h"
07bf635f
RS
41
42#include "dispextern.h"
49fe12a9 43#include "blockinput.h"
07bf635f
RS
44
45#include <X11/StringDefs.h>
46#include <X11/IntrinsicP.h>
47#include <X11/cursorfont.h>
48#include "widgetprv.h"
65fbf4a3 49#include <X11/ObjectP.h>
07bf635f
RS
50#include <X11/Shell.h>
51#include <X11/ShellP.h>
69524b98 52#include "../lwlib/lwlib.h"
07bf635f 53
a5d3ec3f
GM
54#include <signal.h>
55#include "syssignal.h"
56
07bf635f
RS
57/* This sucks: this is the first default that x-faces.el tries. This won't
58 be used unless neither the "Emacs.EmacsFrame" resource nor the
59 "Emacs.EmacsFrame" resource is set; the frame
60 may have the wrong default size if this font doesn't exist, but some other
61 font that x-faces.el does. The workaround is to specify some font in the
62 resource database; I don't know a solution other than duplicating the font-
63 searching code from x-faces.el in this file.
64
65 This also means that if "Emacs.EmacsFrame" is specified as a non-
66 existent font, then Xt is going to substitute "XtDefaultFont" for it,
67 which is a different size than this one. The solution for this is to
68 make x-faces.el try to use XtDefaultFont. The problem with that is that
69 XtDefaultFont is almost certainly variable-width.
70
71 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
72 */
73#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
74
75
01492d1b
RS
76static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
77static void EmacsFrameDestroy (/* Widget */);
78static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
79void EmacsFrameResize (/* Widget widget */);
80static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
81 ArgList, Cardinal * */);
82static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
83 XtWidgetGeometry* */);
07bf635f
RS
84
85
86#undef XtOffset
87#define XtOffset(p_type,field) \
88 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
89#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
90
91static XtResource resources[] = {
92 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
93 offset (geometry), XtRString, (XtPointer) 0},
94 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
95 offset (iconic), XtRImmediate, (XtPointer) False},
96
97 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
98 offset (frame), XtRImmediate, 0},
99
100 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
101 offset (minibuffer), XtRImmediate, (XtPointer)0},
102 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
103 offset (unsplittable), XtRImmediate, (XtPointer)0},
104 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
105 offset (internal_border_width), XtRImmediate, (XtPointer)4},
106 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
107 offset (interline), XtRImmediate, (XtPointer)0},
108 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
109 offset(font),XtRString, DEFAULT_FACE_FONT},
110 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
111 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
112 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
113 offset(cursor_color), XtRString, "XtDefaultForeground"},
114 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
115 offset (bar_cursor), XtRImmediate, (XtPointer)0},
116 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
117 offset (visual_bell), XtRImmediate, (XtPointer)0},
118 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
119 offset (bell_volume), XtRImmediate, (XtPointer)0},
120};
121
122#undef offset
123
124/*
125static XtActionsRec
126emacsFrameActionsTable [] = {
127 {"keypress", key_press},
128 {"focus_in", emacs_frame_focus_handler},
129 {"focus_out", emacs_frame_focus_handler},
130};
131
132static char
133emacsFrameTranslations [] = "\
134<KeyPress>: keypress()\n\
135<FocusIn>: focus_in()\n\
136<FocusOut>: focus_out()\n\
137";
138*/
139
140EmacsFrameClassRec emacsFrameClassRec = {
141 { /* core fields */
142 /* superclass */ &widgetClassRec,
143 /* class_name */ "EmacsFrame",
144 /* widget_size */ sizeof(EmacsFrameRec),
145 /* class_initialize */ 0,
146 /* class_part_initialize */ 0,
147 /* class_inited */ FALSE,
148 /* initialize */ EmacsFrameInitialize,
149 /* initialize_hook */ 0,
150 /* realize */ EmacsFrameRealize,
151 /* actions */ 0, /*emacsFrameActionsTable*/
152 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
153 /* resources */ resources,
154 /* resource_count */ XtNumber(resources),
155 /* xrm_class */ NULLQUARK,
156 /* compress_motion */ TRUE,
157 /* compress_exposure */ TRUE,
158 /* compress_enterleave */ TRUE,
159 /* visible_interest */ FALSE,
160 /* destroy */ EmacsFrameDestroy,
161 /* resize */ EmacsFrameResize,
162 /* expose */ XtInheritExpose,
163 /* set_values */ EmacsFrameSetValues,
164 /* set_values_hook */ 0,
165 /* set_values_almost */ XtInheritSetValuesAlmost,
166 /* get_values_hook */ 0,
167 /* accept_focus */ XtInheritAcceptFocus,
168 /* version */ XtVersion,
169 /* callback_private */ 0,
170 /* tm_table */ 0, /*emacsFrameTranslations*/
171 /* query_geometry */ EmacsFrameQueryGeometry,
172 /* display_accelerator */ XtInheritDisplayAccelerator,
173 /* extension */ 0
174 }
175};
176
177WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
178
179static void
01492d1b
RS
180get_default_char_pixel_size (ew, pixel_width, pixel_height)
181 EmacsFrame ew;
182 int* pixel_width;
183 int* pixel_height;
07bf635f 184{
07bf635f 185 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
186 *pixel_width = FRAME_COLUMN_WIDTH (f);
187 *pixel_height = FRAME_LINE_HEIGHT (f);
07bf635f
RS
188}
189
190static void
01492d1b
RS
191pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
192 EmacsFrame ew;
193 Dimension pixel_width;
194 Dimension pixel_height;
195 int* char_width;
196 int* char_height;
07bf635f
RS
197{
198 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
199 *char_width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, (int) pixel_width);
200 *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height);
07bf635f
RS
201}
202
203static void
345a94f9
RS
204char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
205 EmacsFrame ew;
206 int char_width;
207 int char_height;
208 Dimension* pixel_width;
209 Dimension* pixel_height;
07bf635f
RS
210{
211 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
212 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
213 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
07bf635f
RS
214}
215
216static void
345a94f9
RS
217round_size_to_char (ew, in_width, in_height, out_width, out_height)
218 EmacsFrame ew;
219 Dimension in_width;
220 Dimension in_height;
221 Dimension* out_width;
222 Dimension* out_height;
07bf635f
RS
223{
224 int char_width;
225 int char_height;
226 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
227 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
228}
229
230static Widget
345a94f9
RS
231get_wm_shell (w)
232 Widget w;
07bf635f
RS
233{
234 Widget wmshell;
235
236 for (wmshell = XtParent (w);
237 wmshell && !XtIsWMShell (wmshell);
238 wmshell = XtParent (wmshell));
239
240 return wmshell;
241}
242
ccce6056
GM
243#if 0 /* Currently not used. */
244
07bf635f 245static void
345a94f9
RS
246mark_shell_size_user_specified (wmshell)
247 Widget wmshell;
07bf635f
RS
248{
249 if (! XtIsWMShell (wmshell)) abort ();
250 /* This is kind of sleazy, but I can't see how else to tell it to make it
251 mark the WM_SIZE_HINTS size as user specified when appropriate. */
252 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
253}
254
ccce6056
GM
255#endif
256
07bf635f
RS
257
258/* Can't have static frame locals because of some broken compilers.
259 Normally, initializing a variable like this doesn't work in emacs,
260 but it's ok in this file because it must come after lastfile (and
261 thus have its data not go into text space) because Xt needs to
262 write to initialized data objects too.
263 */
ccce6056 264#if 0
07bf635f 265static Boolean first_frame_p = True;
ccce6056 266#endif
07bf635f
RS
267
268static void
345a94f9
RS
269set_frame_size (ew)
270 EmacsFrame ew;
07bf635f
RS
271{
272 /* The widget hierarchy is
273
274 argv[0] emacsShell pane Frame-NAME
275 ApplicationShell EmacsShell Paned EmacsFrame
276
277 We accept geometry specs in this order:
278
279 *Frame-NAME.geometry
280 *EmacsFrame.geometry
281 Emacs.geometry
282
283 Other possibilities for widget hierarchies might be
284
285 argv[0] frame pane Frame-NAME
286 ApplicationShell EmacsShell Paned EmacsFrame
287 or
288 argv[0] Frame-NAME pane Frame-NAME
289 ApplicationShell EmacsShell Paned EmacsFrame
290 or
291 argv[0] Frame-NAME pane emacsTextPane
292 ApplicationShell EmacsFrame Paned EmacsTextPane
293
294 With the current setup, the text-display-area is the part which is
295 an emacs "frame", since that's the only part managed by emacs proper
296 (the menubar and the parent of the menubar and all that sort of thing
297 are managed by lwlib.)
298
177c0ea7 299 The EmacsShell widget is simply a replacement for the Shell widget
07bf635f
RS
300 which is able to deal with using an externally-supplied window instead
301 of always creating its own. It is not actually emacs specific, and
302 should possibly have class "Shell" instead of "EmacsShell" to simplify
303 the resources.
304
305 */
306
07bf635f 307 /* Hairily merged geometry */
90022f5a
KS
308 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
309 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
177c0ea7 310
07bf635f 311 Widget wmshell = get_wm_shell ((Widget) ew);
38971c41 312 /* Each Emacs shell is now independent and top-level. */
177c0ea7 313
07bf635f 314 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
07bf635f 315
177c0ea7 316 /* We don't need this for the moment. The geometry is computed in
edaf359b
FP
317 xfns.c. */
318#if 0
07bf635f
RS
319 /* If the EmacsFrame doesn't have a geometry but the shell does,
320 treat that as the geometry of the frame. (Is this bogus?
321 I'm not sure.) */
322 if (ew->emacs_frame.geometry == 0)
c52e7aa6 323 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
07bf635f
RS
324
325 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
326 this bogus? I'm not sure.) */
327 if (!ew->emacs_frame.iconic)
c52e7aa6 328 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
177c0ea7
JB
329
330
07bf635f
RS
331 {
332 char *geom = 0;
c52e7aa6 333 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
07bf635f
RS
334 if (geom)
335 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
336 }
177c0ea7 337
07bf635f
RS
338 if (ew->emacs_frame.geometry)
339 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
340 &frame_x, &frame_y,
341 &frame_w, &frame_h);
177c0ea7 342
07bf635f
RS
343 if (first_frame_p)
344 {
345 /* If this is the first frame created:
346 ====================================
347
348 - Use the ApplicationShell's size/position, if specified.
349 (This is "Emacs.geometry", or the "-geometry" command line arg.)
350 - Else use the EmacsFrame's size/position.
351 (This is "*Frame-NAME.geometry")
352
353 - If the AppShell is iconic, the frame should be iconic.
354
355 AppShell comes first so that -geometry always applies to the first
356 frame created, even if there is an "every frame" entry in the
357 resource database.
358 */
359 if (app_flags & (XValue | YValue))
360 {
361 x = app_x; y = app_y;
362 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
363 }
364 else if (frame_flags & (XValue | YValue))
365 {
366 x = frame_x; y = frame_y;
367 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
368 }
369
370 if (app_flags & (WidthValue | HeightValue))
371 {
372 w = app_w; h = app_h;
373 flags |= (app_flags & (WidthValue | HeightValue));
374 }
375 else if (frame_flags & (WidthValue | HeightValue))
376 {
377 w = frame_w; h = frame_h;
378 flags |= (frame_flags & (WidthValue | HeightValue));
379 }
380
381 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
382 if (!ew->emacs_frame.iconic)
c52e7aa6 383 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
07bf635f
RS
384
385 first_frame_p = False;
386 }
387 else
388 {
389 /* If this is not the first frame created:
390 ========================================
391
392 - use the EmacsFrame's size/position if specified
393 - Otherwise, use the ApplicationShell's size, but not position.
394
395 So that means that one can specify the position of the first frame
396 with "Emacs.geometry" or `-geometry'; but can only specify the
397 position of subsequent frames with "*Frame-NAME.geometry".
398
399 AppShell comes second so that -geometry does not apply to subsequent
400 frames when there is an "every frame" entry in the resource db,
401 but does apply to the first frame.
402 */
403 if (frame_flags & (XValue | YValue))
404 {
405 x = frame_x; y = frame_y;
406 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
407 }
408
409 if (frame_flags & (WidthValue | HeightValue))
410 {
411 w = frame_w; h = frame_h;
412 flags |= (frame_flags & (WidthValue | HeightValue));
413 }
414 else if (app_flags & (WidthValue | HeightValue))
415 {
416 w = app_w;
417 h = app_h;
418 flags |= (app_flags & (WidthValue | HeightValue));
419 }
420 }
edaf359b 421#endif /* 0 */
07bf635f 422 {
90022f5a 423 struct frame *f = ew->emacs_frame.frame;
07bf635f 424 Dimension pixel_width, pixel_height;
07bf635f 425
f403d3c3
GM
426 /* Take into account the size of the scrollbar. Always use the
427 number of columns occupied by the scroll bar here otherwise we
428 might end up with a frame width that is not a multiple of the
429 frame's character width which is bad for vertically split
430 windows. */
90022f5a
KS
431 f->scroll_bar_actual_width
432 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
07bf635f 433
90022f5a 434 compute_fringe_widths (f, 0);
f403d3c3 435
de70f8b6
RS
436#if 0 /* This can run Lisp code, and it is dangerous to give
437 out the frame to Lisp code before it officially exists.
438 This is handled in Fx_create_frame so not needed here. */
90022f5a 439 change_frame_size (f, h, w, 1, 0, 0);
de70f8b6 440#endif
07bf635f
RS
441 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
442 ew->core.width = pixel_width;
443 ew->core.height = pixel_height;
444
6ae9a3f2 445#if 0 /* xfns.c takes care of this now. */
07bf635f
RS
446 /* If a position was specified, assign it to the shell widget.
447 (Else WM won't do anything with it.)
448 */
449 if (flags & (XValue | YValue))
450 {
451 /* the tricky things with the sign is to make sure that
452 -0 is printed -0. */
453 int len;
454 char *tem;
455 sprintf (shell_position, "=%c%d%c%d",
456 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
457 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
458 len = strlen (shell_position) + 1;
459 tem = (char *) xmalloc (len);
460 strncpy (tem, shell_position, len);
c52e7aa6 461 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
07bf635f
RS
462 }
463 else if (flags & (WidthValue | HeightValue))
464 {
465 int len;
466 char *tem;
467 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
468 len = strlen (shell_position) + 1;
469 tem = (char *) xmalloc (len);
470 strncpy (tem, shell_position, len);
c52e7aa6 471 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
07bf635f
RS
472 }
473
474 /* If the geometry spec we're using has W/H components, mark the size
475 in the WM_SIZE_HINTS as user specified. */
476 if (flags & (WidthValue | HeightValue))
477 mark_shell_size_user_specified (wmshell);
478
479 /* Also assign the iconic status of the frame to the Shell, so that
480 the WM sees it. */
c52e7aa6 481 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
edaf359b 482#endif /* 0 */
07bf635f
RS
483 }
484}
485
cfcd12d6
KH
486/* Nonzero tells update_wm_hints not to do anything
487 (the caller should call update_wm_hints explicitly later.) */
488int update_hints_inhibit;
07bf635f
RS
489
490static void
345a94f9
RS
491update_wm_hints (ew)
492 EmacsFrame ew;
07bf635f
RS
493{
494 Widget wmshell = get_wm_shell ((Widget)ew);
495 int cw;
496 int ch;
497 Dimension rounded_width;
498 Dimension rounded_height;
499 int char_width;
500 int char_height;
501 int base_width;
502 int base_height;
503 int min_rows = 0, min_cols = 0;
504
cfcd12d6
KH
505 if (update_hints_inhibit)
506 return;
507
508#if 0
07bf635f 509 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
cfcd12d6 510#endif
07bf635f
RS
511
512 pixel_to_char_size (ew, ew->core.width, ew->core.height,
513 &char_width, &char_height);
514 char_to_pixel_size (ew, char_width, char_height,
515 &rounded_width, &rounded_height);
177c0ea7 516 get_default_char_pixel_size (ew, &cw, &ch);
07bf635f
RS
517
518 base_width = (wmshell->core.width - ew->core.width
519 + (rounded_width - (char_width * cw)));
520 base_height = (wmshell->core.height - ew->core.height
521 + (rounded_height - (char_height * ch)));
522
523 /* This is kind of sleazy, but I can't see how else to tell it to
524 make it mark the WM_SIZE_HINTS size as user specified.
525 */
526/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
527
528 XtVaSetValues (wmshell,
cbec8c51
GM
529 XtNbaseWidth, (XtArgVal) base_width,
530 XtNbaseHeight, (XtArgVal) base_height,
177c0ea7 531 XtNwidthInc, (XtArgVal) cw,
cbec8c51
GM
532 XtNheightInc, (XtArgVal) ch,
533 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
534 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
c52e7aa6 535 NULL);
07bf635f
RS
536}
537
ccce6056
GM
538#if 0
539
07bf635f 540static void
345a94f9
RS
541create_frame_gcs (ew)
542 EmacsFrame ew;
07bf635f 543{
7f18598b 544 struct frame *s = ew->emacs_frame.frame;
07bf635f 545
54e9e953 546 s->output_data.x->normal_gc
85e53327
KH
547 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
548 (unsigned long)0, (XGCValues *)0);
54e9e953 549 s->output_data.x->reverse_gc
85e53327
KH
550 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
551 (unsigned long)0, (XGCValues *)0);
54e9e953 552 s->output_data.x->cursor_gc
85e53327
KH
553 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
554 (unsigned long)0, (XGCValues *)0);
f403d3c3
GM
555 s->output_data.x->black_relief.gc = 0;
556 s->output_data.x->white_relief.gc = 0;
07bf635f
RS
557}
558
ccce6056
GM
559#endif /* 0 */
560
1ad2277b
RS
561static char setup_frame_cursor_bits[] =
562{
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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};
568
07bf635f 569static void
345a94f9
RS
570setup_frame_gcs (ew)
571 EmacsFrame ew;
07bf635f
RS
572{
573 XGCValues gc_values;
574 struct frame* s = ew->emacs_frame.frame;
575 Pixmap blank_stipple, blank_tile;
576
07bf635f
RS
577 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
578 XGetGCValues returns uninitialized data when we query the stipple
579 (instead of None or something sensible) and it makes things hard.
580
581 This should be fixed for real by not querying the GCs but instead having
582 some GC-based cache instead of the current face-based cache which doesn't
583 effectively cache all of the GC settings we need to use.
584 */
585
85e53327
KH
586 blank_stipple
587 = XCreateBitmapFromData (XtDisplay (ew),
588 RootWindowOfScreen (XtScreen (ew)),
589 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
590
591 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
592 never actually get used as a background tile!
593 */
85e53327
KH
594 blank_tile
595 = XCreatePixmapFromBitmapData (XtDisplay(ew),
596 RootWindowOfScreen (XtScreen (ew)),
597 setup_frame_cursor_bits, 2, 2,
598 (unsigned long)0, (unsigned long)1,
599 ew->core.depth);
07bf635f
RS
600
601 /* Normal video */
602 gc_values.font = ew->emacs_frame.font->fid;
603 gc_values.foreground = ew->emacs_frame.foreground_pixel;
604 gc_values.background = ew->core.background_pixel;
605 gc_values.graphics_exposures = False;
606 gc_values.stipple = blank_stipple;
607 gc_values.tile = blank_tile;
54e9e953 608 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
07bf635f
RS
609 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
610 | GCStipple | GCTile),
611 &gc_values);
612
613 /* Reverse video style. */
614 gc_values.font = ew->emacs_frame.font->fid;
615 gc_values.foreground = ew->core.background_pixel;
616 gc_values.background = ew->emacs_frame.foreground_pixel;
617 gc_values.graphics_exposures = False;
618 gc_values.stipple = blank_stipple;
619 gc_values.tile = blank_tile;
54e9e953 620 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
07bf635f
RS
621 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
622 | GCStipple | GCTile),
623 &gc_values);
624
625 /* Cursor has to have an empty stipple. */
626 gc_values.font = ew->emacs_frame.font->fid;
627 gc_values.foreground = ew->core.background_pixel;
628 gc_values.background = ew->emacs_frame.cursor_color;
629 gc_values.graphics_exposures = False;
630 gc_values.tile = blank_tile;
85e53327
KH
631 gc_values.stipple
632 = XCreateBitmapFromData (XtDisplay (ew),
633 RootWindowOfScreen (XtScreen (ew)),
634 setup_frame_cursor_bits, 16, 16);
54e9e953 635 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
07bf635f
RS
636 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
637 | GCStipple | GCTile),
638 &gc_values);
639}
640
641static void
345a94f9
RS
642update_various_frame_slots (ew)
643 EmacsFrame ew;
07bf635f 644{
90022f5a
KS
645 struct frame *f = ew->emacs_frame.frame;
646 struct x_output *x = f->output_data.x;
647 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
648 FRAME_PIXEL_WIDTH (f) = ew->core.width;
649 f->internal_border_width = ew->emacs_frame.internal_border_width;
07bf635f
RS
650
651}
652
653static void
345a94f9
RS
654update_from_various_frame_slots (ew)
655 EmacsFrame ew;
07bf635f 656{
90022f5a
KS
657 struct frame *f = ew->emacs_frame.frame;
658 struct x_output *x = f->output_data.x;
659 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
660 ew->core.width = FRAME_PIXEL_WIDTH (f);
07bf635f 661 ew->core.background_pixel = x->background_pixel;
90022f5a 662 ew->emacs_frame.internal_border_width = f->internal_border_width;
07bf635f
RS
663 ew->emacs_frame.font = x->font;
664 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
665 ew->emacs_frame.cursor_color = x->cursor_pixel;
666 ew->core.border_pixel = x->border_pixel;
667}
668
177c0ea7 669static void
345a94f9
RS
670EmacsFrameInitialize (request, new, dum1, dum2)
671 Widget request;
672 Widget new;
673 ArgList dum1;
674 Cardinal *dum2;
07bf635f
RS
675{
676 EmacsFrame ew = (EmacsFrame)new;
677
678 if (!ew->emacs_frame.frame)
679 {
680 fprintf (stderr,
681 "can't create an emacs frame widget without a frame\n");
682 exit (1);
683 }
684
685#if 0 /* done in xfns.c */
686 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
687 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
688 It's unfortunate that we have to do this, but we need to know the font
689 size for frame-sizing purposes before the faces get initialized. If
690 the "default.attributeFont" isn't set, then we use the font of this
691 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
692 the "default" face will use the frame's font if its own is not set,
693 so everything stays in sync -- it's not possible for the frame's font
694 and the default face's font to be different.
695 */
696 {
697 XFontStruct *f = 0;
698 XtResource face_res;
699 face_res.resource_name = "attributeFont";
700 face_res.resource_class = "AttributeFont";
701 face_res.resource_type = XtRFontStruct;
702 face_res.resource_size = sizeof (XFontStruct *);
703 face_res.resource_offset = 0;
704 face_res.default_type = XtRImmediate;
705 face_res.default_addr = 0;
706 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
707 &face_res, 1, NULL, 0);
177c0ea7 708
07bf635f
RS
709 if (f)
710 ew->emacs_frame.font = f;
711 else if (! ew->emacs_frame.font)
712 {
713 fprintf (stderr, "emacs frame widget could not load a font\n");
714 exit (1);
715 }
716 }
717
718/* Update the font field in frame */
90022f5a 719 FRAME_FONT (ew->emacs_frame.frame) = ew->emacs_frame.font;
07bf635f
RS
720#endif
721
722 update_from_various_frame_slots (ew);
177c0ea7 723 set_frame_size (ew);
07bf635f
RS
724/*create_frame_gcs (ew);
725 setup_frame_gcs (ew);
726 update_various_frame_slots (ew); */
727}
728
729
730static void
345a94f9
RS
731EmacsFrameRealize (widget, mask, attrs)
732 Widget widget;
733 XtValueMask *mask;
734 XSetWindowAttributes *attrs;
07bf635f
RS
735{
736 EmacsFrame ew = (EmacsFrame)widget;
737
486a103d
GM
738 /* This used to contain SubstructureRedirectMask, but this turns out
739 to be a problem with XIM on Solaris, and events from that mask
2fce2bb4 740 don't seem to be used. Let's check that. */
486a103d
GM
741 attrs->event_mask = (STANDARD_EVENT_SET
742 | PropertyChangeMask
743 | SubstructureNotifyMask);
07bf635f
RS
744 *mask |= CWEventMask;
745 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
746 attrs);
177c0ea7 747 update_wm_hints (ew);
07bf635f
RS
748}
749
345a94f9 750extern void free_frame_faces (/* struct frame * */);
07bf635f
RS
751
752static void
345a94f9
RS
753EmacsFrameDestroy (widget)
754 Widget widget;
07bf635f
RS
755{
756 EmacsFrame ew = (EmacsFrame) widget;
757 struct frame* s = ew->emacs_frame.frame;
758
759 if (! s) abort ();
54e9e953
KH
760 if (! s->output_data.x) abort ();
761 if (! s->output_data.x->normal_gc) 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'. */
956 XtVaSetValues (f->output_data.x->widget,
957 XtNwaitForWm, (XtArgVal) f->output_data.x->wait_for_wm,
958 NULL);
a5d3ec3f
GM
959
960 /* Workaround: When a SIGIO or SIGALRM occurs while Xt is
961 waiting for a ConfigureNotify event (see above), this leads
962 to Xt waiting indefinitely instead of using its default
963 timeout (5 seconds). */
964 turn_on_atimers (0);
965#ifdef SIGIO
966 sigblock (sigmask (SIGIO));
967#endif
177c0ea7 968
6e7e15f2
GM
969 /* Do parents first, otherwise LessTif's geometry management
970 enters an infinite loop (as of 2000-01-15). This is fixed in
971 later versions of LessTif (as of 2001-03-13); I'll leave it
972 as is because I think it can't do any harm. */
5b48fe65
RS
973 /* In April 2002, simon.marshall@misys.com reports the problem
974 seems not to occur any longer. */
47d09164 975 XtVaSetValues (f->output_data.x->widget,
cbec8c51
GM
976 XtNheight, (XtArgVal) (outer_widget_height + hdelta),
977 XtNwidth, (XtArgVal) (outer_widget_width + wdelta),
978 NULL);
47d09164 979 XtVaSetValues (f->output_data.x->column_widget,
cbec8c51
GM
980 XtNheight, (XtArgVal) (column_widget_height + hdelta),
981 XtNwidth, (XtArgVal) column_widget_width + wdelta,
982 NULL);
47d09164 983 XtVaSetValues ((Widget) ew,
cbec8c51
GM
984 XtNheight, (XtArgVal) pixel_height,
985 XtNwidth, (XtArgVal) pixel_width,
986 NULL);
a5d3ec3f
GM
987#ifdef SIGIO
988 sigunblock (sigmask (SIGIO));
989#endif
990 turn_on_atimers (1);
177c0ea7 991
54e9e953 992 lw_refigure_widget (f->output_data.x->column_widget, True);
50d5aeb5 993
cfcd12d6
KH
994 update_hints_inhibit = 0;
995 update_wm_hints (ew);
996
50d5aeb5 997 /* These seem to get clobbered. I don't know why. - rms. */
54e9e953
KH
998 f->output_data.x->widget->core.x = old_left;
999 f->output_data.x->widget->core.y = old_top;
07bf635f 1000 }
982a94d9
FP
1001
1002 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
1003 receive in the ConfigureNotify event; if we get what we asked
1004 for, then the event won't cause the screen to become garbaged, so
1005 we have to make sure to do it here. */
1006 SET_FRAME_GARBAGED (f);
07bf635f 1007}
f403d3c3 1008
d793b105 1009\f
dfcf069d 1010void
d793b105
RS
1011widget_store_internal_border (widget)
1012 Widget widget;
1013{
1014 EmacsFrame ew = (EmacsFrame) widget;
1015 FRAME_PTR f = ew->emacs_frame.frame;
1016
90022f5a 1017 ew->emacs_frame.internal_border_width = f->internal_border_width;
d793b105 1018}
ab5796a9
MB
1019
1020/* arch-tag: 931d28e5-0d59-405a-8325-7d475d0a13d9
1021 (do not change this comment) */