]> code.delx.au - gnu-emacs/blob - src/widget.c
Trailing whitespace deleted.
[gnu-emacs] / 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., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, 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 = FONT_WIDTH (f->output_data.x->font);
187 *pixel_height = f->output_data.x->line_height;
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 = PIXEL_TO_CHAR_WIDTH (f, (int) pixel_width);
200 *char_height = PIXEL_TO_CHAR_HEIGHT (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 = CHAR_TO_PIXEL_WIDTH (f, char_width);
213 *pixel_height = CHAR_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 = ew->emacs_frame.frame->width;
309 unsigned int h = ew->emacs_frame.frame->height;
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* frame = 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 frame->output_data.x->vertical_scroll_bar_extra
432 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
433 ? 0
434 : (FRAME_SCROLL_BAR_COLS (frame)
435 * FONT_WIDTH (frame->output_data.x->font)));
436
437 x_compute_fringe_widths (frame, 0);
438
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. */
442 change_frame_size (frame, h, w, 1, 0, 0);
443 #endif
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
448 #if 0 /* xfns.c takes care of this now. */
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);
464 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
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);
474 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
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. */
484 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
485 #endif /* 0 */
486 }
487 }
488
489 /* Nonzero tells update_wm_hints not to do anything
490 (the caller should call update_wm_hints explicitly later.) */
491 int update_hints_inhibit;
492
493 static void
494 update_wm_hints (ew)
495 EmacsFrame ew;
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
508 if (update_hints_inhibit)
509 return;
510
511 #if 0
512 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
513 #endif
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);
519 get_default_char_pixel_size (ew, &cw, &ch);
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,
532 XtNbaseWidth, (XtArgVal) base_width,
533 XtNbaseHeight, (XtArgVal) base_height,
534 XtNwidthInc, (XtArgVal) cw,
535 XtNheightInc, (XtArgVal) ch,
536 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
537 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
538 NULL);
539 }
540
541 #if 0
542
543 static void
544 create_frame_gcs (ew)
545 EmacsFrame ew;
546 {
547 struct frame *s = ew->emacs_frame.frame;
548
549 s->output_data.x->normal_gc
550 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
551 (unsigned long)0, (XGCValues *)0);
552 s->output_data.x->reverse_gc
553 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
554 (unsigned long)0, (XGCValues *)0);
555 s->output_data.x->cursor_gc
556 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
557 (unsigned long)0, (XGCValues *)0);
558 s->output_data.x->black_relief.gc = 0;
559 s->output_data.x->white_relief.gc = 0;
560 }
561
562 #endif /* 0 */
563
564 static 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
572 static void
573 setup_frame_gcs (ew)
574 EmacsFrame ew;
575 {
576 XGCValues gc_values;
577 struct frame* s = ew->emacs_frame.frame;
578 Pixmap blank_stipple, blank_tile;
579
580 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
581 XGetGCValues returns uninitialized data when we query the stipple
582 (instead of None or something sensible) and it makes things hard.
583
584 This should be fixed for real by not querying the GCs but instead having
585 some GC-based cache instead of the current face-based cache which doesn't
586 effectively cache all of the GC settings we need to use.
587 */
588
589 blank_stipple
590 = XCreateBitmapFromData (XtDisplay (ew),
591 RootWindowOfScreen (XtScreen (ew)),
592 setup_frame_cursor_bits, 2, 2);
593
594 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
595 never actually get used as a background tile!
596 */
597 blank_tile
598 = XCreatePixmapFromBitmapData (XtDisplay(ew),
599 RootWindowOfScreen (XtScreen (ew)),
600 setup_frame_cursor_bits, 2, 2,
601 (unsigned long)0, (unsigned long)1,
602 ew->core.depth);
603
604 /* Normal video */
605 gc_values.font = ew->emacs_frame.font->fid;
606 gc_values.foreground = ew->emacs_frame.foreground_pixel;
607 gc_values.background = ew->core.background_pixel;
608 gc_values.graphics_exposures = False;
609 gc_values.stipple = blank_stipple;
610 gc_values.tile = blank_tile;
611 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
612 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
613 | GCStipple | GCTile),
614 &gc_values);
615
616 /* Reverse video style. */
617 gc_values.font = ew->emacs_frame.font->fid;
618 gc_values.foreground = ew->core.background_pixel;
619 gc_values.background = ew->emacs_frame.foreground_pixel;
620 gc_values.graphics_exposures = False;
621 gc_values.stipple = blank_stipple;
622 gc_values.tile = blank_tile;
623 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
624 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
625 | GCStipple | GCTile),
626 &gc_values);
627
628 /* Cursor has to have an empty stipple. */
629 gc_values.font = ew->emacs_frame.font->fid;
630 gc_values.foreground = ew->core.background_pixel;
631 gc_values.background = ew->emacs_frame.cursor_color;
632 gc_values.graphics_exposures = False;
633 gc_values.tile = blank_tile;
634 gc_values.stipple
635 = XCreateBitmapFromData (XtDisplay (ew),
636 RootWindowOfScreen (XtScreen (ew)),
637 setup_frame_cursor_bits, 16, 16);
638 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
639 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
640 | GCStipple | GCTile),
641 &gc_values);
642 }
643
644 static void
645 update_various_frame_slots (ew)
646 EmacsFrame ew;
647 {
648 struct x_output *x = ew->emacs_frame.frame->output_data.x;
649 x->pixel_height = ew->core.height + x->menubar_height;
650 x->pixel_width = ew->core.width;
651 x->internal_border_width = ew->emacs_frame.internal_border_width;
652
653 }
654
655 static void
656 update_from_various_frame_slots (ew)
657 EmacsFrame ew;
658 {
659 struct x_output *x = ew->emacs_frame.frame->output_data.x;
660 ew->core.height = x->pixel_height - x->menubar_height;
661 ew->core.width = x->pixel_width;
662 ew->core.background_pixel = x->background_pixel;
663 ew->emacs_frame.internal_border_width = x->internal_border_width;
664 ew->emacs_frame.font = x->font;
665 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
666 ew->emacs_frame.cursor_color = x->cursor_pixel;
667 ew->core.border_pixel = x->border_pixel;
668 }
669
670 static void
671 EmacsFrameInitialize (request, new, dum1, dum2)
672 Widget request;
673 Widget new;
674 ArgList dum1;
675 Cardinal *dum2;
676 {
677 EmacsFrame ew = (EmacsFrame)new;
678
679 if (!ew->emacs_frame.frame)
680 {
681 fprintf (stderr,
682 "can't create an emacs frame widget without a frame\n");
683 exit (1);
684 }
685
686 #if 0 /* done in xfns.c */
687 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
688 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
689 It's unfortunate that we have to do this, but we need to know the font
690 size for frame-sizing purposes before the faces get initialized. If
691 the "default.attributeFont" isn't set, then we use the font of this
692 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
693 the "default" face will use the frame's font if its own is not set,
694 so everything stays in sync -- it's not possible for the frame's font
695 and the default face's font to be different.
696 */
697 {
698 XFontStruct *f = 0;
699 XtResource face_res;
700 face_res.resource_name = "attributeFont";
701 face_res.resource_class = "AttributeFont";
702 face_res.resource_type = XtRFontStruct;
703 face_res.resource_size = sizeof (XFontStruct *);
704 face_res.resource_offset = 0;
705 face_res.default_type = XtRImmediate;
706 face_res.default_addr = 0;
707 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
708 &face_res, 1, NULL, 0);
709
710 if (f)
711 ew->emacs_frame.font = f;
712 else if (! ew->emacs_frame.font)
713 {
714 fprintf (stderr, "emacs frame widget could not load a font\n");
715 exit (1);
716 }
717 }
718
719 /* Update the font field in frame */
720 ew->emacs_frame.frame->output_data.x->font = ew->emacs_frame.font;
721 #endif
722
723 update_from_various_frame_slots (ew);
724 set_frame_size (ew);
725 /*create_frame_gcs (ew);
726 setup_frame_gcs (ew);
727 update_various_frame_slots (ew); */
728 }
729
730
731 static void
732 EmacsFrameRealize (widget, mask, attrs)
733 Widget widget;
734 XtValueMask *mask;
735 XSetWindowAttributes *attrs;
736 {
737 EmacsFrame ew = (EmacsFrame)widget;
738
739 /* This used to contain SubstructureRedirectMask, but this turns out
740 to be a problem with XIM on Solaris, and events from that mask
741 don't seem to be used. Let's check that. */
742 attrs->event_mask = (STANDARD_EVENT_SET
743 | PropertyChangeMask
744 | SubstructureNotifyMask);
745 *mask |= CWEventMask;
746 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
747 attrs);
748 update_wm_hints (ew);
749 }
750
751 extern void free_frame_faces (/* struct frame * */);
752
753 static void
754 EmacsFrameDestroy (widget)
755 Widget widget;
756 {
757 EmacsFrame ew = (EmacsFrame) widget;
758 struct frame* s = ew->emacs_frame.frame;
759
760 if (! s) abort ();
761 if (! s->output_data.x) abort ();
762 if (! s->output_data.x->normal_gc) abort ();
763
764 BLOCK_INPUT;
765 x_free_gcs (s);
766 if (s->output_data.x->white_relief.gc)
767 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
768 if (s->output_data.x->black_relief.gc)
769 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
770 UNBLOCK_INPUT;
771 }
772
773 void
774 EmacsFrameResize (widget)
775 Widget widget;
776 {
777 EmacsFrame ew = (EmacsFrame)widget;
778 struct frame *f = ew->emacs_frame.frame;
779 int columns;
780 int rows;
781
782 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
783 change_frame_size (f, rows, columns, 0, 1, 0);
784 update_wm_hints (ew);
785 update_various_frame_slots (ew);
786
787 cancel_mouse_face (f);
788 }
789
790 static Boolean
791 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
792 Widget cur_widget;
793 Widget req_widget;
794 Widget new_widget;
795 ArgList dum1;
796 Cardinal *dum2;
797 {
798 EmacsFrame cur = (EmacsFrame)cur_widget;
799 EmacsFrame new = (EmacsFrame)new_widget;
800
801 Boolean needs_a_refresh = False;
802 Boolean has_to_recompute_size;
803 Boolean has_to_recompute_gcs;
804 Boolean has_to_update_hints;
805
806 int char_width, char_height;
807 Dimension pixel_width;
808 Dimension pixel_height;
809
810 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
811 || (cur->emacs_frame.foreground_pixel
812 != new->emacs_frame.foreground_pixel)
813 || (cur->core.background_pixel
814 != new->core.background_pixel)
815 );
816
817 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
818 && cur->core.width == new->core.width
819 && cur->core.height == new->core.height);
820
821 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
822
823 if (has_to_recompute_gcs)
824 {
825 setup_frame_gcs (new);
826 needs_a_refresh = True;
827 }
828
829 if (has_to_recompute_size)
830 {
831 pixel_width = new->core.width;
832 pixel_height = new->core.height;
833 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
834 &char_height);
835 char_to_pixel_size (new, char_width, char_height, &pixel_width,
836 &pixel_height);
837 new->core.width = pixel_width;
838 new->core.height = pixel_height;
839
840 change_frame_size (new->emacs_frame.frame, char_height, char_width,
841 1, 0, 0);
842 needs_a_refresh = True;
843 }
844
845 if (has_to_update_hints)
846 update_wm_hints (new);
847
848 update_various_frame_slots (new);
849
850 /* #### This doesn't work, I haven't been able to find ANY kludge that
851 will let (x-create-frame '((iconic . t))) work. It seems that changes
852 to wm_shell's iconic slot have no effect after it has been realized,
853 and calling XIconifyWindow doesn't work either (even though the window
854 has been created.) Perhaps there is some property we could smash
855 directly, but I'm sick of this for now.
856 */
857 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
858 {
859 Widget wmshell = get_wm_shell ((Widget) cur);
860 XtVaSetValues (wmshell, XtNiconic,
861 (XtArgVal) new->emacs_frame.iconic, NULL);
862 }
863
864 return needs_a_refresh;
865 }
866
867 static XtGeometryResult
868 EmacsFrameQueryGeometry (widget, request, result)
869 Widget widget;
870 XtWidgetGeometry* request;
871 XtWidgetGeometry* result;
872 {
873 EmacsFrame ew = (EmacsFrame)widget;
874
875 int mask = request->request_mode;
876 Dimension ok_width, ok_height;
877
878 if (mask & (CWWidth | CWHeight))
879 {
880 round_size_to_char (ew,
881 (mask & CWWidth) ? request->width : ew->core.width,
882 ((mask & CWHeight) ? request->height
883 : ew->core.height),
884 &ok_width, &ok_height);
885 if ((mask & CWWidth) && (ok_width != request->width))
886 {
887 result->request_mode |= CWWidth;
888 result->width = ok_width;
889 }
890 if ((mask & CWHeight) && (ok_height != request->height))
891 {
892 result->request_mode |= CWHeight;
893 result->height = ok_height;
894 }
895 }
896 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
897 }
898
899 /* Special entrypoints */
900 void
901 EmacsFrameSetCharSize (widget, columns, rows)
902 Widget widget;
903 int columns;
904 int rows;
905 {
906 EmacsFrame ew = (EmacsFrame) widget;
907 Dimension pixel_width, pixel_height;
908 struct frame *f = ew->emacs_frame.frame;
909
910 if (columns < 3) columns = 3; /* no way buddy */
911
912 check_frame_size (f, &rows, &columns);
913 f->output_data.x->vertical_scroll_bar_extra
914 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
915 ? 0
916 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
917
918 x_compute_fringe_widths (f, 0);
919
920 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
921
922 #if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
923 /* Something is really strange here wrt to the border width:
924 Apparently, XtNwidth and XtNheight include the border, so we have
925 to add it here. But the XtNborderWidth set for the widgets has
926 no similarity to what f->output_data.x->border_width is set to. */
927 XtVaGetValues (widget, XtNborderWidth, &border_width, NULL);
928 pixel_height += 2 * border_width;
929 pixel_width += 2 * border_width;
930 #endif
931
932 /* Manually change the height and width of all our widgets,
933 adjusting each widget by the same increments. */
934 if (ew->core.width != pixel_width
935 || ew->core.height != pixel_height)
936 {
937 int hdelta = pixel_height - ew->core.height;
938 int wdelta = pixel_width - ew->core.width;
939 int column_widget_height = f->output_data.x->column_widget->core.height;
940 int column_widget_width = f->output_data.x->column_widget->core.width;
941 int outer_widget_height = f->output_data.x->widget->core.height;
942 int outer_widget_width = f->output_data.x->widget->core.width;
943 int old_left = f->output_data.x->widget->core.x;
944 int old_top = f->output_data.x->widget->core.y;
945
946 /* Input is blocked here, and Xt waits for some event to
947 occur. */
948
949 lw_refigure_widget (f->output_data.x->column_widget, False);
950 update_hints_inhibit = 1;
951
952 /* Xt waits for a ConfigureNotify event from the window manager
953 in EmacsFrameSetCharSize when the shell widget is resized.
954 For some window managers like fvwm2 2.2.5 and KDE 2.1 this
955 event doesn't arrive for an unknown reason and Emacs hangs in
956 Xt when the default font is changed. Tell Xt not to wait,
957 depending on the value of the frame parameter
958 `wait-for-wm'. */
959 XtVaSetValues (f->output_data.x->widget,
960 XtNwaitForWm, (XtArgVal) f->output_data.x->wait_for_wm,
961 NULL);
962
963 /* Workaround: When a SIGIO or SIGALRM occurs while Xt is
964 waiting for a ConfigureNotify event (see above), this leads
965 to Xt waiting indefinitely instead of using its default
966 timeout (5 seconds). */
967 turn_on_atimers (0);
968 #ifdef SIGIO
969 sigblock (sigmask (SIGIO));
970 #endif
971
972 /* Do parents first, otherwise LessTif's geometry management
973 enters an infinite loop (as of 2000-01-15). This is fixed in
974 later versions of LessTif (as of 2001-03-13); I'll leave it
975 as is because I think it can't do any harm. */
976 /* In April 2002, simon.marshall@misys.com reports the problem
977 seems not to occur any longer. */
978 XtVaSetValues (f->output_data.x->widget,
979 XtNheight, (XtArgVal) (outer_widget_height + hdelta),
980 XtNwidth, (XtArgVal) (outer_widget_width + wdelta),
981 NULL);
982 XtVaSetValues (f->output_data.x->column_widget,
983 XtNheight, (XtArgVal) (column_widget_height + hdelta),
984 XtNwidth, (XtArgVal) column_widget_width + wdelta,
985 NULL);
986 XtVaSetValues ((Widget) ew,
987 XtNheight, (XtArgVal) pixel_height,
988 XtNwidth, (XtArgVal) pixel_width,
989 NULL);
990 #ifdef SIGIO
991 sigunblock (sigmask (SIGIO));
992 #endif
993 turn_on_atimers (1);
994
995 lw_refigure_widget (f->output_data.x->column_widget, True);
996
997 update_hints_inhibit = 0;
998 update_wm_hints (ew);
999
1000 /* These seem to get clobbered. I don't know why. - rms. */
1001 f->output_data.x->widget->core.x = old_left;
1002 f->output_data.x->widget->core.y = old_top;
1003 }
1004
1005 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
1006 receive in the ConfigureNotify event; if we get what we asked
1007 for, then the event won't cause the screen to become garbaged, so
1008 we have to make sure to do it here. */
1009 SET_FRAME_GARBAGED (f);
1010 }
1011
1012 \f
1013 void
1014 widget_store_internal_border (widget)
1015 Widget widget;
1016 {
1017 EmacsFrame ew = (EmacsFrame) widget;
1018 FRAME_PTR f = ew->emacs_frame.frame;
1019
1020 ew->emacs_frame.internal_border_width
1021 = f->output_data.x->internal_border_width;
1022 }