comparison src/EmacsFrame.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 8de8e3f6228a
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
1 /* The emacs frame widget.
2 Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1993-1995 Sun Microsystems, Inc.
4 Copyright (C) 1995 Ben Wing.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 /* Synched up with: Not in FSF. */
24
25 /* #### Note to potential hackers: Don't mess with this unless you're
26 sure you know what you're doing! Xt is a lot more subtle than
27 you may think. */
28
29 #include <config.h>
30 #include "lisp.h"
31
32 #include "console-x.h"
33 #include "glyphs-x.h"
34 #include "objects-x.h"
35 #include <X11/Shell.h>
36 #include "EmacsFrameP.h"
37 #include "EmacsManager.h" /* for EmacsManagerChangeSize */
38 #include "xmu.h"
39
40 #include "faces.h"
41 #include "frame.h"
42 #include "toolbar.h"
43 #include "window.h"
44
45 static void EmacsFrameClassInitialize (void);
46 static void EmacsFrameInitialize (Widget, Widget, ArgList, Cardinal *);
47 static void EmacsFrameRealize (Widget, XtValueMask*, XSetWindowAttributes*);
48 static void EmacsFrameResize (Widget widget);
49 static Boolean EmacsFrameSetValues (Widget, Widget, Widget,
50 ArgList, Cardinal *);
51 static XtGeometryResult EmacsFrameQueryGeometry (Widget, XtWidgetGeometry*,
52 XtWidgetGeometry*);
53
54 extern void
55 emacs_Xt_mapping_action (Widget w, XEvent* event);
56
57 #undef XtOffset
58 #define XtOffset(p_type,field) \
59 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
60 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
61
62 static XtResource resources[] = {
63 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
64 offset (geometry), XtRString, (XtPointer) 0},
65 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
66 offset (iconic), XtRImmediate, (XtPointer) False},
67
68 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
69 offset (frame), XtRImmediate, 0},
70 {XtNmenubar, XtCMenubar, XtRBoolean, sizeof (Boolean),
71 offset (menubar_p), XtRImmediate, (XtPointer) True},
72 {XtNinitiallyUnmapped, XtCInitiallyUnmapped, XtRBoolean, sizeof (Boolean),
73 offset (initially_unmapped), XtRImmediate, (XtPointer) False},
74 {XtNminibuffer, XtCMinibuffer, XtRBoolean, sizeof (Boolean),
75 offset (minibuffer), XtRImmediate, (XtPointer) True},
76 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
77 offset (unsplittable), XtRImmediate, (XtPointer) False},
78 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
79 offset (internal_border_width), XtRImmediate, (XtPointer)4},
80 #ifdef HAVE_SCROLLBARS
81 {XtNscrollBarWidth, XtCScrollBarWidth, XtRInt, sizeof (int),
82 offset (scrollbar_width), XtRImmediate, (XtPointer)-1},
83 {XtNscrollBarHeight, XtCScrollBarHeight, XtRInt, sizeof (int),
84 offset (scrollbar_height), XtRImmediate, (XtPointer)-1},
85 {XtNscrollBarPlacement, XtCScrollBarPlacement, XtRScrollBarPlacement,
86 sizeof(unsigned char), offset(scrollbar_placement), XtRImmediate,
87 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) || \
88 defined (LWLIB_SCROLLBARS_ATHENA3D)
89 (XtPointer) XtBOTTOM_RIGHT
90 #else
91 (XtPointer) XtBOTTOM_LEFT
92 #endif
93 },
94 #endif /* HAVE_SCROLLBARS */
95 #ifdef HAVE_TOOLBARS
96 {XtNtopToolBarHeight, XtCTopToolBarHeight, XtRInt, sizeof (int),
97 offset (top_toolbar_height), XtRImmediate, (XtPointer)-1},
98 {XtNbottomToolBarHeight, XtCBottomToolBarHeight, XtRInt, sizeof (int),
99 offset (bottom_toolbar_height), XtRImmediate, (XtPointer)-1},
100 {XtNleftToolBarWidth, XtCLeftToolBarWidth, XtRInt, sizeof (int),
101 offset (left_toolbar_width), XtRImmediate, (XtPointer)-1},
102 {XtNrightToolBarWidth, XtCRightToolBarWidth, XtRInt, sizeof (int),
103 offset (right_toolbar_width), XtRImmediate, (XtPointer)-1},
104 {XtNtopToolBarBorderWidth, XtCTopToolBarBorderWidth, XtRInt,
105 sizeof (int),
106 offset (top_toolbar_border_width), XtRImmediate, (XtPointer)-1},
107 {XtNbottomToolBarBorderWidth, XtCBottomToolBarBorderWidth, XtRInt,
108 sizeof (int),
109 offset (bottom_toolbar_border_width), XtRImmediate, (XtPointer)-1},
110 {XtNleftToolBarBorderWidth, XtCLeftToolBarBorderWidth, XtRInt,
111 sizeof (int),
112 offset (left_toolbar_border_width), XtRImmediate, (XtPointer)-1},
113 {XtNrightToolBarBorderWidth, XtCRightToolBarBorderWidth, XtRInt,
114 sizeof (int),
115 offset (right_toolbar_border_width), XtRImmediate, (XtPointer)-1},
116 {XtNtopToolBarShadowColor, XtCTopToolBarShadowColor, XtRPixel, sizeof(Pixel),
117 offset(top_toolbar_shadow_pixel), XtRString, (XtPointer) "#000000"},
118 {XtNbottomToolBarShadowColor, XtCBottomToolBarShadowColor, XtRPixel,
119 sizeof(Pixel), offset(bottom_toolbar_shadow_pixel), XtRString, (XtPointer) "#000000"},
120 {XtNbackgroundToolBarColor, XtCBackgroundToolBarColor, XtRPixel,
121 sizeof(Pixel), offset(background_toolbar_pixel), XtRImmediate,
122 (XtPointer)-1},
123 {XtNforegroundToolBarColor, XtCForegroundToolBarColor, XtRPixel,
124 sizeof(Pixel), offset(foreground_toolbar_pixel), XtRImmediate,
125 (XtPointer)-1},
126 {XtNtopToolBarShadowPixmap, XtCTopToolBarShadowPixmap, XtRPixmap,
127 sizeof (Pixmap), offset(top_toolbar_shadow_pixmap), XtRImmediate,
128 (XtPointer)None},
129 {XtNbottomToolBarShadowPixmap, XtCBottomToolBarShadowPixmap, XtRPixmap,
130 sizeof (Pixmap), offset(bottom_toolbar_shadow_pixmap), XtRImmediate,
131 (XtPointer)None},
132 {XtNtoolBarShadowThickness, XtCToolBarShadowThickness, XtRDimension,
133 sizeof (Dimension), offset (toolbar_shadow_thickness), XtRImmediate,
134 (XtPointer)2},
135 #endif /* HAVE_TOOLBARS */
136 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
137 offset (interline), XtRImmediate, (XtPointer)0},
138 {
139 #ifdef I18N4
140 XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet),
141 #else
142 XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
143 #endif
144 offset(font), XtRImmediate, (XtPointer)0
145 },
146 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
147 offset(foreground_pixel), XtRString, (XtPointer) "Black"},
148 {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
149 offset(background_pixel), XtRString, (XtPointer) "Gray80"},
150 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
151 offset(cursor_color), XtRString, (XtPointer) "XtDefaultForeground"},
152 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
153 offset (bar_cursor), XtRImmediate, (XtPointer)0},
154 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
155 offset (visual_bell), XtRImmediate, (XtPointer)0},
156 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
157 offset (bell_volume), XtRImmediate, (XtPointer)0},
158 {XtNuseBackingStore, XtCUseBackingStore, XtRBoolean, sizeof (Boolean),
159 offset (use_backing_store), XtRImmediate, (XtPointer)0},
160 {XtNpreferredWidth, XtCPreferredWidth, XtRDimension, sizeof (Dimension),
161 offset (preferred_width), XtRImmediate, (XtPointer)0},
162 {XtNpreferredHeight, XtCPreferredHeight, XtRDimension, sizeof (Dimension),
163 offset (preferred_height), XtRImmediate, (XtPointer)0},
164 };
165
166 #undef offset
167
168 /* Xt is stupid and dumb.
169 Xt is stupid and dumb.
170 Xt is stupid and dumb. */
171
172 static XtActionsRec
173 emacsFrameActionsTable [] = {
174 {"mapping", (XtActionProc) emacs_Xt_mapping_action},
175 };
176
177 static char
178 emacsFrameTranslations [] = "\
179 <Mapping>: mapping()\n\
180 ";
181
182 /* If we're running under Motif, make this widget a subclass
183 of XmPrimitive. It's not clear this is necessary, but it
184 may make focus behavior work better. */
185
186 EmacsFrameClassRec emacsFrameClassRec = {
187 { /* core fields */
188 #ifdef LWLIB_USES_MOTIF
189 /* superclass */ (WidgetClass) &xmPrimitiveClassRec,
190 #else
191 /* superclass */ &widgetClassRec,
192 #endif
193 /* class_name */ "EmacsFrame",
194 /* widget_size */ sizeof(EmacsFrameRec),
195 /* class_initialize */ EmacsFrameClassInitialize,
196 /* class_part_initialize */ 0,
197 /* class_inited */ FALSE,
198 /* initialize */ EmacsFrameInitialize,
199 /* initialize_hook */ 0,
200 /* realize */ EmacsFrameRealize,
201 /* actions */ emacsFrameActionsTable,
202 /* num_actions */ XtNumber (emacsFrameActionsTable),
203 /* resources */ resources,
204 /* resource_count */ XtNumber(resources),
205 /* xrm_class */ NULLQUARK,
206 /* compress_motion */ TRUE,
207 /* compress_exposure */ TRUE,
208 /* compress_enterleave */ TRUE,
209 /* visible_interest */ FALSE,
210 /* destroy */ NULL,
211 /* resize */ EmacsFrameResize,
212 /* expose */ XtInheritExpose,
213 /* set_values */ EmacsFrameSetValues,
214 /* set_values_hook */ 0,
215 /* set_values_almost */ XtInheritSetValuesAlmost,
216 /* get_values_hook */ 0,
217 /* accept_focus */ XtInheritAcceptFocus,
218 /* version */ XtVersion,
219 /* callback_private */ 0,
220 /* tm_table */ emacsFrameTranslations,
221 /* query_geometry */ EmacsFrameQueryGeometry,
222 /* display_accelerator */ XtInheritDisplayAccelerator,
223 /* extension */ 0
224 },
225 #ifdef LWLIB_USES_MOTIF
226 { /* XmPrimitiveClassPart
227 */
228 (XtWidgetProc) _XtInherit, /* border_highlight */
229 (XtWidgetProc) _XtInherit, /* border_unhighlight */
230 /* Setting the following to NULL causes PrimitiveInitialize()
231 not to add traversal (TAB etc. to switch focus) and
232 focus-in/out (border highlight/unhighlight) translations.
233 If you want those translations, use the value XtInheritTranslations
234 instead. Doing this, however, will interfere with Emacs
235 focus handling (which highlights/unhighlights the text cursor),
236 and will lead to strange display results around the border of the
237 widget. */
238 NULL, /* translations */
239 NULL, /* arm_and_activate */
240 NULL, /* get resources */
241 0, /* num get_resources */
242 NULL, /* extension */
243 },
244 #endif /* LWLIB_USES_MOTIF */
245 {
246 0
247 }
248 };
249 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
250
251 static void
252 update_various_frame_slots (EmacsFrame ew)
253 {
254 ew->emacs_frame.frame->pixheight = ew->core.height;
255 ew->emacs_frame.frame->pixwidth = ew->core.width;
256 }
257
258 static void
259 EmacsFrameInitialize (Widget request, Widget new,
260 ArgList dum1, Cardinal *dum2)
261 {
262 EmacsFrame ew = (EmacsFrame)new;
263 struct frame *f = ew->emacs_frame.frame;
264
265 if (!f)
266 fatal ("can't create an emacs frame widget without a frame.");
267
268 ew->emacs_frame.frame->internal_border_width =
269 ew->emacs_frame.internal_border_width;
270 }
271
272 void emacs_Xt_event_handler (Widget wid /* unused */,
273 XtPointer closure /* unused */,
274 XEvent *event,
275 Boolean *continue_to_dispatch /* unused */);
276
277 static void
278 EmacsFrameRealize (Widget widget, XtValueMask *mask,
279 XSetWindowAttributes *attrs)
280 {
281 EmacsFrame ew = (EmacsFrame) widget;
282 struct frame *f = ew->emacs_frame.frame;
283 Widget shell_widget = FRAME_X_SHELL_WIDGET (f);
284
285 attrs->event_mask =
286 ExposureMask |
287 VisibilityChangeMask |
288 PropertyChangeMask |
289 StructureNotifyMask |
290 SubstructureNotifyMask |
291 /*SubstructureRedirectMask |*/ /* Only for WMs! */
292 KeyPressMask |
293 KeyReleaseMask |
294 ButtonPressMask |
295 ButtonReleaseMask |
296 FocusChangeMask |
297 PointerMotionHintMask |
298 PointerMotionMask |
299 LeaveWindowMask |
300 EnterWindowMask;
301
302
303 #ifdef I18N4
304 /* Make sure that events wanted by the input method are selected. */
305 attrs->event_mask |= input_method_event_mask;
306 #endif
307
308 *mask |= CWEventMask;
309
310 if (ew->emacs_frame.use_backing_store)
311 {
312 attrs->backing_store = Always;
313 *mask |= CWBackingStore;
314 }
315 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
316 attrs);
317
318 /* snarf the events we want. */
319 XtInsertEventHandler (widget, attrs->event_mask, TRUE,
320 emacs_Xt_event_handler, NULL, XtListHead);
321 /* some events (e.g. map-notify and WM_DELETE_WINDOW) get sent
322 directly to the shell, and the above event handler won't see
323 them. So add a handler to get them. These events don't
324 propagate, so there's no danger of them being seen twice. */
325 XtInsertEventHandler (shell_widget,
326 EnterWindowMask | LeaveWindowMask |
327 VisibilityChangeMask | StructureNotifyMask |
328 KeyPressMask,
329 TRUE, emacs_Xt_event_handler, NULL, XtListHead);
330
331 #ifdef EXTERNAL_WIDGET
332 /* #### Not sure if this special case is necessary */
333 if (!FRAME_X_EXTERNAL_WINDOW_P (f))
334 #endif
335 /* This is necessary under Motif in order to make it possible to click in
336 a buffer and move focus out of a dialog box or control panel and back
337 into emacs-land; also necessary so that you can still type chars
338 if the cursor is over the menubar or scrollbar. */
339 lw_set_keyboard_focus (shell_widget, FRAME_X_TEXT_WIDGET (f));
340 }
341
342 /* DO NOT CALL THIS FUNCTION! Only Xt is supposed to do this. */
343
344 static void
345 EmacsFrameResize (Widget widget)
346 {
347 EmacsFrame ew = (EmacsFrame)widget;
348 struct frame *f = ew->emacs_frame.frame;
349 int columns;
350 int rows;
351 XtWidgetGeometry req, repl;
352
353 update_various_frame_slots (ew);
354
355 pixel_to_char_size (f, ew->core.width, ew->core.height, &columns, &rows);
356 change_frame_size (f, rows, columns, 0);
357
358 /* Now we tell the EmacsShell that we've changed the size of the non-fixed
359 portion of the frame. Note that, if we the resize occurred as a result
360 of EmacsFrameSetCharSize(), this information will be stored twice.
361 This is not a big deal, as storing this information doesn't actually
362 do anything until the next resize. */
363 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
364 x_wm_set_variable_size (FRAME_X_SHELL_WIDGET (f), columns, rows);
365
366 /* Kick the manager so that it knows we've changed size. */
367 req.request_mode = 0;
368 XtQueryGeometry (FRAME_X_CONTAINER_WIDGET (f), &req, &repl);
369 EmacsManagerChangeSize (FRAME_X_CONTAINER_WIDGET (f), repl.width,
370 repl.height);
371 }
372
373 static Boolean
374 EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget,
375 ArgList argv, Cardinal *argc)
376 {
377 EmacsFrame cur = (EmacsFrame) cur_widget;
378 EmacsFrame new = (EmacsFrame) new_widget;
379 struct frame *f = new->emacs_frame.frame;
380 Lisp_Object frame;
381
382 XSETFRAME (frame, f);
383 in_resource_setting++;
384 /* This function does not need to do much. Pretty much everything
385 interesting will get done in the resize method, which will
386 (if necessary) get called by Xt when this function returns
387 (see below).
388 */
389
390 /* #### This function will not work if it is not called from
391 update_EmacsFrame(), called from SET_FACE_PROPERTY().
392 The code located there should be moved inside of here instead,
393 so that things work if either SET_FACE_PROPERTY() is
394 called or XtSetValues() is called.
395 */
396
397 if (cur->emacs_frame.iconic != new->emacs_frame.iconic &&
398 FRAME_X_TOP_LEVEL_FRAME_P (new->emacs_frame.frame))
399 x_wm_set_shell_iconic_p (FRAME_X_SHELL_WIDGET (new->emacs_frame.frame),
400 new->emacs_frame.iconic);
401
402 /* If we got here, then we were likely called as a result of
403 the EditRes protocol, so go ahead and change scrollbar-width
404 and scrollbar-height. Otherwise, we're merely mirroring
405 a change made to scrollbar-width etc. so don't do anything
406 special. */
407 if (cur->emacs_frame.internal_border_width !=
408 new->emacs_frame.internal_border_width)
409 {
410 f->internal_border_width = new->emacs_frame.internal_border_width;
411 MARK_FRAME_SIZE_SLIPPED (f);
412 }
413
414 #ifdef HAVE_SCROLLBARS
415 if (cur->emacs_frame.scrollbar_width !=
416 new->emacs_frame.scrollbar_width)
417 Fadd_spec_to_specifier
418 (Vscrollbar_width,
419 make_int (new->emacs_frame.scrollbar_width),
420 frame, Qnil, Qnil);
421 if (cur->emacs_frame.scrollbar_height !=
422 new->emacs_frame.scrollbar_height)
423 Fadd_spec_to_specifier
424 (Vscrollbar_height,
425 make_int (new->emacs_frame.scrollbar_height),
426 frame, Qnil, Qnil);
427 #endif /* HAVE_SCROLLBARS */
428 #ifdef HAVE_TOOLBARS
429 if (cur->emacs_frame.top_toolbar_height !=
430 new->emacs_frame.top_toolbar_height)
431 Fadd_spec_to_specifier
432 (Vtoolbar_size[TOP_TOOLBAR],
433 make_int (new->emacs_frame.top_toolbar_height),
434 frame, Qnil, Qnil);
435 if (cur->emacs_frame.bottom_toolbar_height !=
436 new->emacs_frame.bottom_toolbar_height)
437 Fadd_spec_to_specifier
438 (Vtoolbar_size[BOTTOM_TOOLBAR],
439 make_int (new->emacs_frame.bottom_toolbar_height),
440 frame, Qnil, Qnil);
441 if (cur->emacs_frame.left_toolbar_width !=
442 new->emacs_frame.left_toolbar_width)
443 Fadd_spec_to_specifier
444 (Vtoolbar_size[LEFT_TOOLBAR],
445 make_int (new->emacs_frame.left_toolbar_width),
446 frame, Qnil, Qnil);
447 if (cur->emacs_frame.right_toolbar_width !=
448 new->emacs_frame.right_toolbar_width)
449 Fadd_spec_to_specifier
450 (Vtoolbar_size[RIGHT_TOOLBAR],
451 make_int (new->emacs_frame.right_toolbar_width),
452 frame, Qnil, Qnil);
453 if (cur->emacs_frame.top_toolbar_border_width !=
454 new->emacs_frame.top_toolbar_border_width)
455 Fadd_spec_to_specifier
456 (Vtoolbar_border_width[TOP_TOOLBAR],
457 make_int (new->emacs_frame.top_toolbar_border_width),
458 frame, Qnil, Qnil);
459 if (cur->emacs_frame.bottom_toolbar_border_width !=
460 new->emacs_frame.bottom_toolbar_border_width)
461 Fadd_spec_to_specifier
462 (Vtoolbar_border_width[BOTTOM_TOOLBAR],
463 make_int (new->emacs_frame.bottom_toolbar_border_width),
464 frame, Qnil, Qnil);
465 if (cur->emacs_frame.left_toolbar_border_width !=
466 new->emacs_frame.left_toolbar_border_width)
467 Fadd_spec_to_specifier
468 (Vtoolbar_border_width[LEFT_TOOLBAR],
469 make_int (new->emacs_frame.left_toolbar_border_width),
470 frame, Qnil, Qnil);
471 if (cur->emacs_frame.right_toolbar_border_width !=
472 new->emacs_frame.right_toolbar_border_width)
473 Fadd_spec_to_specifier
474 (Vtoolbar_border_width[RIGHT_TOOLBAR],
475 make_int (new->emacs_frame.right_toolbar_border_width),
476 frame, Qnil, Qnil);
477 #endif /* HAVE_TOOLBARS */
478
479 in_resource_setting--;
480
481 /* If the request was to resize us, but the size has not changed, Xt
482 will do nothing, and won't call our resize callback. Since such a
483 request might be issued as a result of hiding/showing menubar or
484 changing toolbar placement, where we rely on relayout made by the
485 callback, we go ahead and simulate such a call */
486 if (cur->core.width == new->core.width
487 && cur->core.height == new->core.height)
488 {
489 int i;
490 for (i=0; i<*argc; i++)
491 if (strcmp (argv[i].name, XtNwidth) == 0
492 || strcmp (argv[i].name, XtNheight) == 0)
493 {
494 EmacsFrameResize (new_widget);
495 break;
496 }
497 }
498
499 return False;
500
501 /* Note that if either (a) we return True, or (b) the width or
502 height has changed, an Expose event will be generated. The Xt
503 manual says you should not return True if the width or height has
504 changed, because then two Expose events will be generated.
505
506 In any case, there is no need to return True because
507 SET_FACE_PROPERTY(), which does the resource
508 setting, automatically forces a redisplay as necessary. */
509 }
510
511 static XtGeometryResult
512 EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request,
513 XtWidgetGeometry *result)
514 {
515 EmacsFrame ew = (EmacsFrame) widget;
516 int mask = request->request_mode;
517 Dimension width, height;
518 int ok_width_int, ok_height_int;
519 Dimension ok_width, ok_height;
520
521 /* We have a definite preference for what size we would like
522 to be.
523
524 1) If a preferred size was specified for us, use it.
525 (This is not currently used)
526 2) If a proposed size was given, round it to the nearest
527 multiple of the default char size and return it.
528 3) Otherwise, take our current size and round it to the
529 nearest multiple of the default char size. */
530
531 width = mask & CWWidth ? request->width : ew->core.width;
532 height = mask & CWHeight ? request->height : ew->core.height;
533 round_size_to_char (ew->emacs_frame.frame, width, height,
534 &ok_width_int, &ok_height_int);
535 ok_width = (Dimension) ok_width_int;
536 ok_height = (Dimension) ok_height_int;
537 if (ew->emacs_frame.preferred_width)
538 ok_width = ew->emacs_frame.preferred_width;
539 if (ew->emacs_frame.preferred_height)
540 ok_height = ew->emacs_frame.preferred_height;
541 result->request_mode |= CWWidth | CWHeight;
542 result->width = ok_width;
543 result->height = ok_height;
544 if (((mask & CWWidth) && ok_width != request->width)
545 || ((mask & CWHeight) && ok_height != request->height))
546 return XtGeometryAlmost;
547 else
548 return XtGeometryYes;
549 }
550
551 /* Xt string-to-scrollbar-placement converter */
552 /* ### Convert this to a `new-style' converter (See XtAddTypeConverter) */
553
554 /* This variable cannot be a stack variable. */
555 static unsigned char cvt_string_scrollbar_placement;
556
557 /* ARGSUSED */
558 static void
559 Xt_StringToScrollBarPlacement (XrmValuePtr args, /* unused */
560 Cardinal *num_args, /* unused */
561 XrmValuePtr fromVal,
562 XrmValuePtr toVal)
563 {
564 XrmQuark q;
565 char *lowerName = (char *) alloca (strlen ((char *) fromVal->addr) + 1);
566
567 XmuCopyISOLatin1Lowered (lowerName, (char *) fromVal->addr);
568 q = XrmStringToQuark (lowerName);
569
570 toVal->size = sizeof (cvt_string_scrollbar_placement);
571 toVal->addr = (XPointer) &cvt_string_scrollbar_placement;
572
573 if (q == XrmStringToQuark ("top-left")
574 || q == XrmStringToQuark ("top_left"))
575 cvt_string_scrollbar_placement = XtTOP_LEFT;
576 else if (q == XrmStringToQuark ("bottom-left")
577 || q == XrmStringToQuark ("bottom_left"))
578 cvt_string_scrollbar_placement = XtBOTTOM_LEFT;
579 else if (q == XrmStringToQuark ("top-right")
580 || q == XrmStringToQuark ("top_right"))
581 cvt_string_scrollbar_placement = XtTOP_RIGHT;
582 else if (q == XrmStringToQuark ("bottom-right")
583 || q == XrmStringToQuark ("bottom_right"))
584 cvt_string_scrollbar_placement = XtBOTTOM_RIGHT;
585 else
586 {
587 XtStringConversionWarning (fromVal->addr, "scrollBarPlacement");
588 toVal->addr = NULL;
589 toVal->size = 0;
590 }
591 }
592
593 static void
594 EmacsFrameClassInitialize (void)
595 {
596 XtAddConverter (XtRString, XtRScrollBarPlacement,
597 Xt_StringToScrollBarPlacement, NULL, 0);
598 }
599
600 /********************* Special entrypoints *******************/
601
602 void
603 EmacsFrameRecomputeCellSize (Widget w)
604 {
605 EmacsFrame ew = (EmacsFrame) w;
606 int cw, ch;
607 struct frame *f = ew->emacs_frame.frame;
608
609 if (! XtIsSubclass (w, emacsFrameClass))
610 abort ();
611
612 default_face_height_and_width (make_frame (f), &ch, &cw);
613 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
614 x_wm_set_cell_size (FRAME_X_SHELL_WIDGET (f), cw, ch);
615 }
616
617 /* Set the size of the widget to have the number of rows and columns
618 specified. This both causes the X window to change and the
619 internal frame structures to get modified to match. */
620
621 void
622 EmacsFrameSetCharSize (Widget widget, int columns, int rows)
623 {
624 EmacsFrame ew = (EmacsFrame) widget;
625 int pixel_width, pixel_height;
626 struct frame *f = ew->emacs_frame.frame;
627
628 if (columns < 3)
629 columns = 3; /* no way buddy */
630 if (rows < 1)
631 rows = 1;
632
633 char_to_pixel_size (f, columns, rows, &pixel_width, &pixel_height);
634
635 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
636 x_wm_set_variable_size (FRAME_X_SHELL_WIDGET (f), columns, rows);
637
638 {
639 Arg al [2];
640 XtSetArg (al [0], XtNwidth, pixel_width);
641 XtSetArg (al [1], XtNheight, pixel_height);
642 XtSetValues ((Widget) ew, al, countof (al));
643 }
644 }