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