Update FSF's address.
[bpt/emacs.git] / src / widget.c
1 /* The emacs frame widget.
2 Copyright (C) 1992, 1993, 2000 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
20
21 /* Emacs 19 face widget ported by Fred Pierresteguy */
22
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
33 #include <config.h>
34 #include <stdio.h>
35 #include "lisp.h"
36 #include "xterm.h"
37
38 #include "keyboard.h"
39 #include "frame.h"
40 #include "window.h"
41
42 #include "dispextern.h"
43 #include "blockinput.h"
44
45 #include <X11/StringDefs.h>
46 #include <X11/IntrinsicP.h>
47 #include <X11/cursorfont.h>
48 #include "widgetprv.h"
49 #include <X11/ObjectP.h>
50 #include <X11/Shell.h>
51 #include <X11/ShellP.h>
52 #include "../lwlib/lwlib.h"
53
54 #include <signal.h>
55 #include "syssignal.h"
56
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
76 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
77 static void EmacsFrameDestroy (/* Widget */);
78 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
79 void EmacsFrameResize (/* Widget widget */);
80 static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
81 ArgList, Cardinal * */);
82 static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
83 XtWidgetGeometry* */);
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
91 static 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 /*
125 static XtActionsRec
126 emacsFrameActionsTable [] = {
127 {"keypress", key_press},
128 {"focus_in", emacs_frame_focus_handler},
129 {"focus_out", emacs_frame_focus_handler},
130 };
131
132 static char
133 emacsFrameTranslations [] = "\
134 <KeyPress>: keypress()\n\
135 <FocusIn>: focus_in()\n\
136 <FocusOut>: focus_out()\n\
137 ";
138 */
139
140 EmacsFrameClassRec 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
177 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
178
179 static void
180 get_default_char_pixel_size (ew, pixel_width, pixel_height)
181 EmacsFrame ew;
182 int* pixel_width;
183 int* pixel_height;
184 {
185 struct frame* f = ew->emacs_frame.frame;
186 *pixel_width = FRAME_COLUMN_WIDTH (f);
187 *pixel_height = FRAME_LINE_HEIGHT (f);
188 }
189
190 static void
191 pixel_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;
197 {
198 struct frame* f = ew->emacs_frame.frame;
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);
201 }
202
203 static void
204 char_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;
210 {
211 struct frame* f = ew->emacs_frame.frame;
212 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
213 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
214 }
215
216 static void
217 round_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;
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
230 static Widget
231 get_wm_shell (w)
232 Widget w;
233 {
234 Widget wmshell;
235
236 for (wmshell = XtParent (w);
237 wmshell && !XtIsWMShell (wmshell);
238 wmshell = XtParent (wmshell));
239
240 return wmshell;
241 }
242
243 #if 0 /* Currently not used. */
244
245 static void
246 mark_shell_size_user_specified (wmshell)
247 Widget wmshell;
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
255 #endif
256
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 */
264 #if 0
265 static Boolean first_frame_p = True;
266 #endif
267
268 static void
269 set_frame_size (ew)
270 EmacsFrame ew;
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
299 The EmacsShell widget is simply a replacement for the Shell widget
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
307 /* Hairily merged geometry */
308 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
309 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
310
311 Widget wmshell = get_wm_shell ((Widget) ew);
312 /* Each Emacs shell is now independent and top-level. */
313
314 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
315
316 /* We don't need this for the moment. The geometry is computed in
317 xfns.c. */
318 #if 0
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)
323 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
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)
328 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
329
330
331 {
332 char *geom = 0;
333 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
334 if (geom)
335 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
336 }
337
338 if (ew->emacs_frame.geometry)
339 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
340 &frame_x, &frame_y,
341 &frame_w, &frame_h);
342
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)
383 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
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 }
421 #endif /* 0 */
422 {
423 struct frame *f = ew->emacs_frame.frame;
424 Dimension pixel_width, pixel_height;
425
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. */
431 f->scroll_bar_actual_width
432 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
433
434 compute_fringe_widths (f, 0);
435
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. */
439 change_frame_size (f, h, w, 1, 0, 0);
440 #endif
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
445 #if 0 /* xfns.c takes care of this now. */
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);
461 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
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);
471 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
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. */
481 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
482 #endif /* 0 */
483 }
484 }
485
486 /* Nonzero tells update_wm_hints not to do anything
487 (the caller should call update_wm_hints explicitly later.) */
488 int update_hints_inhibit;
489
490 static void
491 update_wm_hints (ew)
492 EmacsFrame ew;
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
505 if (update_hints_inhibit)
506 return;
507
508 #if 0
509 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
510 #endif
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);
516 get_default_char_pixel_size (ew, &cw, &ch);
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,
529 XtNbaseWidth, (XtArgVal) base_width,
530 XtNbaseHeight, (XtArgVal) base_height,
531 XtNwidthInc, (XtArgVal) cw,
532 XtNheightInc, (XtArgVal) ch,
533 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
534 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
535 NULL);
536 }
537
538 #if 0
539
540 static void
541 create_frame_gcs (ew)
542 EmacsFrame ew;
543 {
544 struct frame *s = ew->emacs_frame.frame;
545
546 s->output_data.x->normal_gc
547 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
548 (unsigned long)0, (XGCValues *)0);
549 s->output_data.x->reverse_gc
550 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
551 (unsigned long)0, (XGCValues *)0);
552 s->output_data.x->cursor_gc
553 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
554 (unsigned long)0, (XGCValues *)0);
555 s->output_data.x->black_relief.gc = 0;
556 s->output_data.x->white_relief.gc = 0;
557 }
558
559 #endif /* 0 */
560
561 static 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
569 static void
570 setup_frame_gcs (ew)
571 EmacsFrame ew;
572 {
573 XGCValues gc_values;
574 struct frame* s = ew->emacs_frame.frame;
575 Pixmap blank_stipple, blank_tile;
576
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
586 blank_stipple
587 = XCreateBitmapFromData (XtDisplay (ew),
588 RootWindowOfScreen (XtScreen (ew)),
589 setup_frame_cursor_bits, 2, 2);
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 */
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);
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;
608 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
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;
620 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
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;
631 gc_values.stipple
632 = XCreateBitmapFromData (XtDisplay (ew),
633 RootWindowOfScreen (XtScreen (ew)),
634 setup_frame_cursor_bits, 16, 16);
635 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
636 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
637 | GCStipple | GCTile),
638 &gc_values);
639 }
640
641 static void
642 update_various_frame_slots (ew)
643 EmacsFrame ew;
644 {
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;
650
651 }
652
653 static void
654 update_from_various_frame_slots (ew)
655 EmacsFrame ew;
656 {
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);
661 ew->core.background_pixel = x->background_pixel;
662 ew->emacs_frame.internal_border_width = f->internal_border_width;
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
669 static void
670 EmacsFrameInitialize (request, new, dum1, dum2)
671 Widget request;
672 Widget new;
673 ArgList dum1;
674 Cardinal *dum2;
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);
708
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 */
719 FRAME_FONT (ew->emacs_frame.frame) = ew->emacs_frame.font;
720 #endif
721
722 update_from_various_frame_slots (ew);
723 set_frame_size (ew);
724 /*create_frame_gcs (ew);
725 setup_frame_gcs (ew);
726 update_various_frame_slots (ew); */
727 }
728
729
730 static void
731 EmacsFrameRealize (widget, mask, attrs)
732 Widget widget;
733 XtValueMask *mask;
734 XSetWindowAttributes *attrs;
735 {
736 EmacsFrame ew = (EmacsFrame)widget;
737
738 /* This used to contain SubstructureRedirectMask, but this turns out
739 to be a problem with XIM on Solaris, and events from that mask
740 don't seem to be used. Let's check that. */
741 attrs->event_mask = (STANDARD_EVENT_SET
742 | PropertyChangeMask
743 | SubstructureNotifyMask);
744 *mask |= CWEventMask;
745 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
746 attrs);
747 update_wm_hints (ew);
748 }
749
750 extern void free_frame_faces (/* struct frame * */);
751
752 static void
753 EmacsFrameDestroy (widget)
754 Widget widget;
755 {
756 EmacsFrame ew = (EmacsFrame) widget;
757 struct frame* s = ew->emacs_frame.frame;
758
759 if (! s) abort ();
760 if (! s->output_data.x) abort ();
761
762 BLOCK_INPUT;
763 x_free_gcs (s);
764 if (s->output_data.x->white_relief.gc)
765 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
766 if (s->output_data.x->black_relief.gc)
767 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
768 UNBLOCK_INPUT;
769 }
770
771 void
772 EmacsFrameResize (widget)
773 Widget widget;
774 {
775 EmacsFrame ew = (EmacsFrame)widget;
776 struct frame *f = ew->emacs_frame.frame;
777 int columns;
778 int rows;
779
780 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
781 change_frame_size (f, rows, columns, 0, 1, 0);
782 update_wm_hints (ew);
783 update_various_frame_slots (ew);
784
785 cancel_mouse_face (f);
786 }
787
788 static Boolean
789 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
790 Widget cur_widget;
791 Widget req_widget;
792 Widget new_widget;
793 ArgList dum1;
794 Cardinal *dum2;
795 {
796 EmacsFrame cur = (EmacsFrame)cur_widget;
797 EmacsFrame new = (EmacsFrame)new_widget;
798
799 Boolean needs_a_refresh = False;
800 Boolean has_to_recompute_size;
801 Boolean has_to_recompute_gcs;
802 Boolean has_to_update_hints;
803
804 int char_width, char_height;
805 Dimension pixel_width;
806 Dimension pixel_height;
807
808 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
809 || (cur->emacs_frame.foreground_pixel
810 != new->emacs_frame.foreground_pixel)
811 || (cur->core.background_pixel
812 != new->core.background_pixel)
813 );
814
815 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
816 && cur->core.width == new->core.width
817 && cur->core.height == new->core.height);
818
819 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
820
821 if (has_to_recompute_gcs)
822 {
823 setup_frame_gcs (new);
824 needs_a_refresh = True;
825 }
826
827 if (has_to_recompute_size)
828 {
829 pixel_width = new->core.width;
830 pixel_height = new->core.height;
831 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
832 &char_height);
833 char_to_pixel_size (new, char_width, char_height, &pixel_width,
834 &pixel_height);
835 new->core.width = pixel_width;
836 new->core.height = pixel_height;
837
838 change_frame_size (new->emacs_frame.frame, char_height, char_width,
839 1, 0, 0);
840 needs_a_refresh = True;
841 }
842
843 if (has_to_update_hints)
844 update_wm_hints (new);
845
846 update_various_frame_slots (new);
847
848 /* #### This doesn't work, I haven't been able to find ANY kludge that
849 will let (x-create-frame '((iconic . t))) work. It seems that changes
850 to wm_shell's iconic slot have no effect after it has been realized,
851 and calling XIconifyWindow doesn't work either (even though the window
852 has been created.) Perhaps there is some property we could smash
853 directly, but I'm sick of this for now.
854 */
855 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
856 {
857 Widget wmshell = get_wm_shell ((Widget) cur);
858 XtVaSetValues (wmshell, XtNiconic,
859 (XtArgVal) new->emacs_frame.iconic, NULL);
860 }
861
862 return needs_a_refresh;
863 }
864
865 static XtGeometryResult
866 EmacsFrameQueryGeometry (widget, request, result)
867 Widget widget;
868 XtWidgetGeometry* request;
869 XtWidgetGeometry* result;
870 {
871 EmacsFrame ew = (EmacsFrame)widget;
872
873 int mask = request->request_mode;
874 Dimension ok_width, ok_height;
875
876 if (mask & (CWWidth | CWHeight))
877 {
878 round_size_to_char (ew,
879 (mask & CWWidth) ? request->width : ew->core.width,
880 ((mask & CWHeight) ? request->height
881 : ew->core.height),
882 &ok_width, &ok_height);
883 if ((mask & CWWidth) && (ok_width != request->width))
884 {
885 result->request_mode |= CWWidth;
886 result->width = ok_width;
887 }
888 if ((mask & CWHeight) && (ok_height != request->height))
889 {
890 result->request_mode |= CWHeight;
891 result->height = ok_height;
892 }
893 }
894 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
895 }
896
897 /* Special entrypoints */
898 void
899 EmacsFrameSetCharSize (widget, columns, rows)
900 Widget widget;
901 int columns;
902 int rows;
903 {
904 EmacsFrame ew = (EmacsFrame) widget;
905 Dimension pixel_width, pixel_height;
906 struct frame *f = ew->emacs_frame.frame;
907
908 if (columns < 3) columns = 3; /* no way buddy */
909
910 check_frame_size (f, &rows, &columns);
911 f->scroll_bar_actual_width
912 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
913
914 compute_fringe_widths (f, 0);
915
916 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
917
918 #if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
919 /* Something is really strange here wrt to the border width:
920 Apparently, XtNwidth and XtNheight include the border, so we have
921 to add it here. But the XtNborderWidth set for the widgets has
922 no similarity to what f->border_width is set to. */
923 XtVaGetValues (widget, XtNborderWidth, &border_width, NULL);
924 pixel_height += 2 * border_width;
925 pixel_width += 2 * border_width;
926 #endif
927
928 /* Manually change the height and width of all our widgets,
929 adjusting each widget by the same increments. */
930 if (ew->core.width != pixel_width
931 || ew->core.height != pixel_height)
932 {
933 int hdelta = pixel_height - ew->core.height;
934 int wdelta = pixel_width - ew->core.width;
935 int column_widget_height = f->output_data.x->column_widget->core.height;
936 int column_widget_width = f->output_data.x->column_widget->core.width;
937 int outer_widget_height = f->output_data.x->widget->core.height;
938 int outer_widget_width = f->output_data.x->widget->core.width;
939 int old_left = f->output_data.x->widget->core.x;
940 int old_top = f->output_data.x->widget->core.y;
941
942 /* Input is blocked here, and Xt waits for some event to
943 occur. */
944
945 lw_refigure_widget (f->output_data.x->column_widget, False);
946 update_hints_inhibit = 1;
947
948 /* Xt waits for a ConfigureNotify event from the window manager
949 in EmacsFrameSetCharSize when the shell widget is resized.
950 For some window managers like fvwm2 2.2.5 and KDE 2.1 this
951 event doesn't arrive for an unknown reason and Emacs hangs in
952 Xt when the default font is changed. Tell Xt not to wait,
953 depending on the value of the frame parameter
954 `wait-for-wm'. */
955 XtVaSetValues (f->output_data.x->widget,
956 XtNwaitForWm, (XtArgVal) f->output_data.x->wait_for_wm,
957 NULL);
958
959 /* Workaround: When a SIGIO or SIGALRM occurs while Xt is
960 waiting for a ConfigureNotify event (see above), this leads
961 to Xt waiting indefinitely instead of using its default
962 timeout (5 seconds). */
963 turn_on_atimers (0);
964 #ifdef SIGIO
965 sigblock (sigmask (SIGIO));
966 #endif
967
968 /* Do parents first, otherwise LessTif's geometry management
969 enters an infinite loop (as of 2000-01-15). This is fixed in
970 later versions of LessTif (as of 2001-03-13); I'll leave it
971 as is because I think it can't do any harm. */
972 /* In April 2002, simon.marshall@misys.com reports the problem
973 seems not to occur any longer. */
974 XtVaSetValues (f->output_data.x->widget,
975 XtNheight, (XtArgVal) (outer_widget_height + hdelta),
976 XtNwidth, (XtArgVal) (outer_widget_width + wdelta),
977 NULL);
978 XtVaSetValues (f->output_data.x->column_widget,
979 XtNheight, (XtArgVal) (column_widget_height + hdelta),
980 XtNwidth, (XtArgVal) column_widget_width + wdelta,
981 NULL);
982 XtVaSetValues ((Widget) ew,
983 XtNheight, (XtArgVal) pixel_height,
984 XtNwidth, (XtArgVal) pixel_width,
985 NULL);
986 #ifdef SIGIO
987 sigunblock (sigmask (SIGIO));
988 #endif
989 turn_on_atimers (1);
990
991 lw_refigure_widget (f->output_data.x->column_widget, True);
992
993 update_hints_inhibit = 0;
994 update_wm_hints (ew);
995
996 /* These seem to get clobbered. I don't know why. - rms. */
997 f->output_data.x->widget->core.x = old_left;
998 f->output_data.x->widget->core.y = old_top;
999 }
1000
1001 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
1002 receive in the ConfigureNotify event; if we get what we asked
1003 for, then the event won't cause the screen to become garbaged, so
1004 we have to make sure to do it here. */
1005 SET_FRAME_GARBAGED (f);
1006 }
1007
1008 \f
1009 void
1010 widget_store_internal_border (widget)
1011 Widget widget;
1012 {
1013 EmacsFrame ew = (EmacsFrame) widget;
1014 FRAME_PTR f = ew->emacs_frame.frame;
1015
1016 ew->emacs_frame.internal_border_width = f->internal_border_width;
1017 }
1018
1019 /* arch-tag: 931d28e5-0d59-405a-8325-7d475d0a13d9
1020 (do not change this comment) */