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