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.
6 This file is part of SXEmacs
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* Synched up with: Not in FSF. */
24 /* #### Note to potential hackers: Don't mess with this unless you're
25 sure you know what you're doing! Xt is a lot more subtle than
31 #include "ui/X11/console-x.h"
32 #include "ui/X11/glyphs-x.h"
33 #include "ui/X11/objects-x.h"
34 #include <X11/Shell.h>
35 #include "EmacsFrameP.h"
36 #include "EmacsManager.h" /* for EmacsManagerChangeSize */
37 #include "ui/X11/xmu.h"
41 #include "ui/toolbar.h"
42 #include "ui/window.h"
44 static void EmacsFrameClassInitialize(void);
45 static void EmacsFrameInitialize(Widget, Widget, ArgList, Cardinal *);
46 static void EmacsFrameRealize(Widget, XtValueMask *, XSetWindowAttributes *);
47 static void EmacsFrameResize(Widget widget);
48 static Boolean EmacsFrameSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
49 static XtGeometryResult EmacsFrameQueryGeometry(Widget, XtWidgetGeometry *,
52 extern void emacs_Xt_mapping_action(Widget w, XEvent * event);
55 #define XtOffset(p_type,field) \
56 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
57 #define offset(field) XtOffset (EmacsFrame, emacs_frame.field)
59 static XtResource resources[] = {
60 {XtNgeometry, XtCGeometry,
61 XtRString, sizeof(String),
62 offset(geometry), XtRString, (XtPointer) 0}
64 {XtNiconic, XtCIconic,
65 XtRBoolean, sizeof(Boolean),
66 offset(iconic), XtRImmediate, (XtPointer) False}
69 {XtNemacsFrame, XtCEmacsFrame,
70 XtRPointer, sizeof(XtPointer),
71 offset(frame), XtRImmediate, 0}
73 {XtNmenubar, XtCMenubar,
74 XtRBoolean, sizeof(Boolean),
75 offset(menubar_p), XtRImmediate, (XtPointer) True}
77 {XtNinitiallyUnmapped, XtCInitiallyUnmapped,
78 XtRBoolean, sizeof(Boolean),
79 offset(initially_unmapped), XtRImmediate, (XtPointer) False}
81 {XtNminibuffer, XtCMinibuffer,
82 XtRBoolean, sizeof(Boolean),
83 offset(minibuffer), XtRImmediate, (XtPointer) True}
85 {XtNunsplittable, XtCUnsplittable,
86 XtRBoolean, sizeof(Boolean),
87 offset(unsplittable), XtRImmediate, (XtPointer) False}
89 {XtNinternalBorderWidth, XtCInternalBorderWidth,
91 offset(internal_border_width), XtRImmediate, (XtPointer) 4},
92 #ifdef HAVE_SCROLLBARS
93 {XtNscrollBarWidth, XtCScrollBarWidth,
95 offset(scrollbar_width), XtRImmediate, (XtPointer) - 1},
96 {XtNscrollBarHeight, XtCScrollBarHeight,
98 offset(scrollbar_height), XtRImmediate, (XtPointer) - 1},
99 {XtNscrollBarPlacement, XtCScrollBarPlacement,
100 XtRScrollBarPlacement, sizeof(unsigned char),
101 offset(scrollbar_placement), XtRImmediate,
102 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) || \
103 defined (LWLIB_SCROLLBARS_ATHENA3D)
104 (XtPointer) XtBOTTOM_RIGHT
106 (XtPointer) XtBOTTOM_LEFT
109 #endif /* HAVE_SCROLLBARS */
112 {XtNtopToolBarHeight, XtCTopToolBarHeight,
114 offset(top_toolbar_height), XtRImmediate, (XtPointer) - 1},
115 {XtNbottomToolBarHeight, XtCBottomToolBarHeight,
117 offset(bottom_toolbar_height), XtRImmediate, (XtPointer) - 1},
118 {XtNleftToolBarWidth, XtCLeftToolBarWidth,
120 offset(left_toolbar_width), XtRImmediate, (XtPointer) - 1},
121 {XtNrightToolBarWidth, XtCRightToolBarWidth,
123 offset(right_toolbar_width), XtRImmediate, (XtPointer) - 1},
124 {XtNtopToolBarBorderWidth, XtCTopToolBarBorderWidth,
126 offset(top_toolbar_border_width), XtRImmediate, (XtPointer) - 1},
127 {XtNbottomToolBarBorderWidth, XtCBottomToolBarBorderWidth,
129 offset(bottom_toolbar_border_width), XtRImmediate, (XtPointer) - 1},
130 {XtNleftToolBarBorderWidth, XtCLeftToolBarBorderWidth,
132 offset(left_toolbar_border_width), XtRImmediate, (XtPointer) - 1},
133 {XtNrightToolBarBorderWidth, XtCRightToolBarBorderWidth,
135 offset(right_toolbar_border_width), XtRImmediate, (XtPointer) - 1},
136 {XtNtopToolBarShadowColor, XtCTopToolBarShadowColor,
137 XtRPixel, sizeof(Pixel),
138 offset(top_toolbar_shadow_pixel), XtRString, (XtPointer) "#000000"}
140 {XtNbottomToolBarShadowColor, XtCBottomToolBarShadowColor,
141 XtRPixel, sizeof(Pixel),
142 offset(bottom_toolbar_shadow_pixel), XtRString, (XtPointer) "#000000"}
144 {XtNbackgroundToolBarColor, XtCBackgroundToolBarColor,
145 XtRPixel, sizeof(Pixel),
146 offset(background_toolbar_pixel), XtRImmediate, (XtPointer) - 1}
148 {XtNforegroundToolBarColor, XtCForegroundToolBarColor,
149 XtRPixel, sizeof(Pixel),
150 offset(foreground_toolbar_pixel), XtRImmediate, (XtPointer) - 1}
152 {XtNtopToolBarShadowPixmap, XtCTopToolBarShadowPixmap,
153 XtRPixmap, sizeof(Pixmap),
154 offset(top_toolbar_shadow_pixmap), XtRImmediate, (XtPointer) None}
156 {XtNbottomToolBarShadowPixmap, XtCBottomToolBarShadowPixmap,
157 XtRPixmap, sizeof(Pixmap),
158 offset(bottom_toolbar_shadow_pixmap), XtRImmediate, (XtPointer) None}
160 {XtNtoolBarShadowThickness, XtCToolBarShadowThickness,
161 XtRDimension, sizeof(Dimension),
162 offset(toolbar_shadow_thickness), XtRImmediate, (XtPointer) 2}
164 #endif /* HAVE_TOOLBARS */
166 {XtNinterline, XtCInterline,
168 offset(interline), XtRImmediate, (XtPointer) 0},
171 XtNfontSet, XtCFontSet,
172 XtRFontSet, sizeof(XFontSet),
175 XtRFontStruct, sizeof(XFontStruct *),
177 offset(font), XtRImmediate, (XtPointer) 0}
179 {XtNforeground, XtCForeground,
180 XtRPixel, sizeof(Pixel),
181 offset(foreground_pixel), XtRString, (XtPointer) "Black"}
183 {XtNbackground, XtCBackground,
184 XtRPixel, sizeof(Pixel),
185 offset(background_pixel), XtRString, (XtPointer) "Gray80"}
187 {XtNcursorColor, XtCForeground,
188 XtRPixel, sizeof(Pixel),
189 offset(cursor_color), XtRString, (XtPointer) "XtDefaultForeground"}
191 {XtNbarCursor, XtCBarCursor,
192 XtRBoolean, sizeof(Boolean),
193 offset(bar_cursor), XtRImmediate, (XtPointer) 0}
195 {XtNvisualBell, XtCVisualBell,
196 XtRBoolean, sizeof(Boolean),
197 offset(visual_bell), XtRImmediate, (XtPointer) 0}
199 {XtNbellVolume, XtCBellVolume,
201 offset(bell_volume), XtRImmediate, (XtPointer) 0},
202 {XtNuseBackingStore, XtCUseBackingStore,
203 XtRBoolean, sizeof(Boolean),
204 offset(use_backing_store), XtRImmediate, (XtPointer) NotUseful}
206 {XtNpreferredWidth, XtCPreferredWidth,
207 XtRDimension, sizeof(Dimension),
208 offset(preferred_width), XtRImmediate, (XtPointer) 0}
210 {XtNpreferredHeight, XtCPreferredHeight,
211 XtRDimension, sizeof(Dimension),
212 offset(preferred_height), XtRImmediate, (XtPointer) 0}
218 /* Xt is stupid and dumb.
219 Xt is stupid and dumb.
220 Xt is stupid and dumb. */
222 static XtActionsRec emacsFrameActionsTable[] = {
223 {"mapping", (XtActionProc) emacs_Xt_mapping_action},
226 static char emacsFrameTranslations[] = "\
227 <Mapping>: mapping()\n\
230 /* If we're running under Motif, make this widget a subclass
231 of XmPrimitive. It's not clear this is necessary, but it
232 may make focus behavior work better. */
234 EmacsFrameClassRec emacsFrameClassRec = {
236 #ifdef LWLIB_USES_MOTIF
237 /* superclass */ (WidgetClass) & xmPrimitiveClassRec,
239 /* superclass */ &widgetClassRec,
241 /* class_name */ "EmacsFrame",
242 /* widget_size */ sizeof(EmacsFrameRec),
243 /* class_initialize */ EmacsFrameClassInitialize,
244 /* class_part_initialize */ 0,
245 /* class_inited */ FALSE,
246 /* initialize */ EmacsFrameInitialize,
247 /* initialize_hook */ 0,
248 /* realize */ EmacsFrameRealize,
249 /* actions */ emacsFrameActionsTable,
250 /* num_actions */ XtNumber(emacsFrameActionsTable),
251 /* resources */ resources,
252 /* resource_count */ XtNumber(resources),
253 /* xrm_class */ NULLQUARK,
254 /* compress_motion */ TRUE,
255 #ifdef LWLIB_USES_MOTIF
256 /* compress_exposure */ TRUE,
258 /* compress_exposure */
259 XtExposeCompressMaximal | XtExposeNoRegion,
261 /* compress_enterleave */ TRUE,
262 /* visible_interest */ FALSE,
264 /* resize */ EmacsFrameResize,
265 /* expose */ XtInheritExpose,
266 /* set_values */ EmacsFrameSetValues,
267 /* set_values_hook */ 0,
268 /* set_values_almost */ XtInheritSetValuesAlmost,
269 /* get_values_hook */ 0,
270 /* accept_focus */ XtInheritAcceptFocus,
271 /* version */ XtVersion,
272 /* callback_private */ 0,
273 /* tm_table */ emacsFrameTranslations,
274 /* query_geometry */ EmacsFrameQueryGeometry,
275 /* display_accelerator */ XtInheritDisplayAccelerator,
279 #ifdef LWLIB_USES_MOTIF
280 { /* XmPrimitiveClassPart
282 (XtWidgetProc) _XtInherit, /* border_highlight */
283 (XtWidgetProc) _XtInherit, /* border_unhighlight */
284 /* Setting the following to NULL causes PrimitiveInitialize()
285 not to add traversal (TAB etc. to switch focus) and
286 focus-in/out (border highlight/unhighlight) translations.
287 If you want those translations, use the value XtInheritTranslations
288 instead. Doing this, however, will interfere with Emacs
289 focus handling (which highlights/unhighlights the text cursor),
290 and will lead to strange display results around the border of the
292 NULL, /* translations */
293 NULL, /* arm_and_activate */
294 NULL, /* get resources */
295 0, /* num get_resources */
296 NULL, /* extension */
299 #endif /* LWLIB_USES_MOTIF */
303 WidgetClass emacsFrameClass = (WidgetClass) & emacsFrameClassRec;
305 static void update_various_frame_slots(EmacsFrame ew)
307 ew->emacs_frame.frame->pixheight = ew->core.height;
308 ew->emacs_frame.frame->pixwidth = ew->core.width;
312 EmacsFrameInitialize(Widget request, Widget new, ArgList dum1, Cardinal * dum2)
314 EmacsFrame ew = (EmacsFrame) new;
315 struct frame *f = ew->emacs_frame.frame;
318 fatal("can't create an emacs frame widget without a frame.");
320 ew->emacs_frame.frame->internal_border_width =
321 ew->emacs_frame.internal_border_width;
324 void emacs_Xt_event_handler(Widget wid /* unused */ ,
325 XtPointer closure /* unused */ ,
327 Boolean * continue_to_dispatch /* unused */ );
330 EmacsFrameRealize(Widget widget, XtValueMask * mask,
331 XSetWindowAttributes * attrs)
333 EmacsFrame ew = (EmacsFrame) widget;
334 struct frame *f = ew->emacs_frame.frame;
335 Widget shell_widget = FRAME_X_SHELL_WIDGET(f);
339 VisibilityChangeMask |
340 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask |
341 /*SubstructureRedirectMask | *//* Only for WMs! */
347 PointerMotionHintMask |
348 PointerMotionMask | LeaveWindowMask | EnterWindowMask;
351 /* Make sure that events wanted by the input method are selected. */
352 attrs->event_mask |= input_method_event_mask;
355 *mask |= CWEventMask;
357 if (ew->emacs_frame.use_backing_store) {
358 attrs->backing_store = Always;
359 *mask |= CWBackingStore;
361 XtCreateWindow(widget, InputOutput, (Visual *) CopyFromParent, *mask,
364 /* snarf the events we want. */
365 XtInsertEventHandler(widget, attrs->event_mask, TRUE,
366 emacs_Xt_event_handler, NULL, XtListHead);
367 /* some events (e.g. map-notify and WM_DELETE_WINDOW) get sent
368 directly to the shell, and the above event handler won't see
369 them. So add a handler to get them. These events don't
370 propagate, so there's no danger of them being seen twice. */
371 XtInsertEventHandler(shell_widget,
372 EnterWindowMask | LeaveWindowMask |
373 VisibilityChangeMask | StructureNotifyMask |
375 TRUE, emacs_Xt_event_handler, NULL, XtListHead);
377 #ifdef EXTERNAL_WIDGET
378 /* #### Not sure if this special case is necessary */
379 if (!FRAME_X_EXTERNAL_WINDOW_P(f))
381 /* This is necessary under Motif in order to make it possible to click in
382 a buffer and move focus out of a dialog box or control panel and back
383 into emacs-land; also necessary so that you can still type chars
384 if the cursor is over the menubar or scrollbar. */
385 lw_set_keyboard_focus(shell_widget, FRAME_X_TEXT_WIDGET(f));
388 /* DO NOT CALL THIS FUNCTION! Only Xt is supposed to do this. */
390 static void EmacsFrameResize(Widget widget)
392 EmacsFrame ew = (EmacsFrame) widget;
393 struct frame *f = ew->emacs_frame.frame;
396 XtWidgetGeometry req, repl;
398 update_various_frame_slots(ew);
400 pixel_to_char_size(f, ew->core.width, ew->core.height, &columns, &rows);
401 change_frame_size(f, rows, columns, 0);
403 /* Now we tell the EmacsShell that we've changed the size of the non-fixed
404 portion of the frame. Note that, if we the resize occurred as a result
405 of EmacsFrameSetCharSize(), this information will be stored twice.
406 This is not a big deal, as storing this information doesn't actually
407 do anything until the next resize. */
408 if (FRAME_X_TOP_LEVEL_FRAME_P(f))
409 x_wm_set_variable_size(FRAME_X_SHELL_WIDGET(f), columns, rows);
411 /* Kick the manager so that it knows we've changed size. */
412 req.request_mode = 0;
413 XtQueryGeometry(FRAME_X_CONTAINER_WIDGET(f), &req, &repl);
414 EmacsManagerChangeSize(FRAME_X_CONTAINER_WIDGET(f), repl.width,
419 EmacsFrameSetValues(Widget cur_widget, Widget req_widget, Widget new_widget,
420 ArgList argv, Cardinal * argc)
422 EmacsFrame cur = (EmacsFrame) cur_widget;
423 EmacsFrame new = (EmacsFrame) new_widget;
424 struct frame *f = new->emacs_frame.frame;
428 in_resource_setting++;
429 /* This function does not need to do much. Pretty much everything
430 interesting will get done in the resize method, which will
431 (if necessary) get called by Xt when this function returns
435 /* #### This function will not work if it is not called from
436 update_EmacsFrame(), called from SET_FACE_PROPERTY().
437 The code located there should be moved inside of here instead,
438 so that things work if either SET_FACE_PROPERTY() is
439 called or XtSetValues() is called.
442 if (cur->emacs_frame.iconic != new->emacs_frame.iconic &&
443 FRAME_X_TOP_LEVEL_FRAME_P(new->emacs_frame.frame))
444 x_wm_set_shell_iconic_p(FRAME_X_SHELL_WIDGET
445 (new->emacs_frame.frame),
446 new->emacs_frame.iconic);
448 /* If we got here, then we were likely called as a result of
449 the EditRes protocol, so go ahead and change scrollbar-width
450 and scrollbar-height. Otherwise, we're merely mirroring
451 a change made to scrollbar-width etc. so don't do anything
453 if (cur->emacs_frame.internal_border_width !=
454 new->emacs_frame.internal_border_width) {
455 f->internal_border_width =
456 new->emacs_frame.internal_border_width;
457 MARK_FRAME_SIZE_SLIPPED(f);
459 #ifdef HAVE_SCROLLBARS
460 if (cur->emacs_frame.scrollbar_width !=
461 new->emacs_frame.scrollbar_width)
462 Fadd_spec_to_specifier
464 make_int(new->emacs_frame.scrollbar_width),
466 if (cur->emacs_frame.scrollbar_height !=
467 new->emacs_frame.scrollbar_height)
468 Fadd_spec_to_specifier
470 make_int(new->emacs_frame.scrollbar_height),
472 #endif /* HAVE_SCROLLBARS */
474 if (cur->emacs_frame.top_toolbar_height !=
475 new->emacs_frame.top_toolbar_height)
476 Fadd_spec_to_specifier
477 (Vtoolbar_size[TOP_TOOLBAR],
478 make_int(new->emacs_frame.top_toolbar_height),
480 if (cur->emacs_frame.bottom_toolbar_height !=
481 new->emacs_frame.bottom_toolbar_height)
482 Fadd_spec_to_specifier
483 (Vtoolbar_size[BOTTOM_TOOLBAR],
484 make_int(new->emacs_frame.bottom_toolbar_height),
486 if (cur->emacs_frame.left_toolbar_width !=
487 new->emacs_frame.left_toolbar_width)
488 Fadd_spec_to_specifier
489 (Vtoolbar_size[LEFT_TOOLBAR],
490 make_int(new->emacs_frame.left_toolbar_width),
492 if (cur->emacs_frame.right_toolbar_width !=
493 new->emacs_frame.right_toolbar_width)
494 Fadd_spec_to_specifier
495 (Vtoolbar_size[RIGHT_TOOLBAR],
496 make_int(new->emacs_frame.right_toolbar_width),
498 if (cur->emacs_frame.top_toolbar_border_width !=
499 new->emacs_frame.top_toolbar_border_width)
500 Fadd_spec_to_specifier
501 (Vtoolbar_border_width[TOP_TOOLBAR],
502 make_int(new->emacs_frame.top_toolbar_border_width),
504 if (cur->emacs_frame.bottom_toolbar_border_width !=
505 new->emacs_frame.bottom_toolbar_border_width)
506 Fadd_spec_to_specifier
507 (Vtoolbar_border_width[BOTTOM_TOOLBAR],
508 make_int(new->emacs_frame.bottom_toolbar_border_width),
510 if (cur->emacs_frame.left_toolbar_border_width !=
511 new->emacs_frame.left_toolbar_border_width)
512 Fadd_spec_to_specifier
513 (Vtoolbar_border_width[LEFT_TOOLBAR],
514 make_int(new->emacs_frame.left_toolbar_border_width),
516 if (cur->emacs_frame.right_toolbar_border_width !=
517 new->emacs_frame.right_toolbar_border_width)
518 Fadd_spec_to_specifier
519 (Vtoolbar_border_width[RIGHT_TOOLBAR],
520 make_int(new->emacs_frame.right_toolbar_border_width),
522 #endif /* HAVE_TOOLBARS */
524 in_resource_setting--;
526 /* If the request was to resize us, but the size has not changed, Xt
527 will do nothing, and won't call our resize callback. Since such a
528 request might be issued as a result of hiding/showing menubar or
529 changing toolbar placement, where we rely on relayout made by the
530 callback, we go ahead and simulate such a call */
531 if (cur->core.width == new->core.width
532 && cur->core.height == new->core.height) {
534 for (i = 0; i < *argc; i++)
535 if (strcmp(argv[i].name, XtNwidth) == 0
536 || strcmp(argv[i].name, XtNheight) == 0) {
537 EmacsFrameResize(new_widget);
544 /* Note that if either (a) we return True, or (b) the width or
545 height has changed, an Expose event will be generated. The Xt
546 manual says you should not return True if the width or height has
547 changed, because then two Expose events will be generated.
549 In any case, there is no need to return True because
550 SET_FACE_PROPERTY(), which does the resource
551 setting, automatically forces a redisplay as necessary. */
554 static XtGeometryResult
555 EmacsFrameQueryGeometry(Widget widget, XtWidgetGeometry * request,
556 XtWidgetGeometry * result)
558 EmacsFrame ew = (EmacsFrame) widget;
559 int mask = request->request_mode;
560 Dimension width, height;
561 int ok_width_int, ok_height_int;
562 Dimension ok_width, ok_height;
564 /* We have a definite preference for what size we would like
567 1) If a preferred size was specified for us, use it.
568 (This is not currently used)
569 2) If a proposed size was given, round it to the nearest
570 multiple of the default char size and return it.
571 3) Otherwise, take our current size and round it to the
572 nearest multiple of the default char size. */
574 width = mask & CWWidth ? request->width : ew->core.width;
575 height = mask & CWHeight ? request->height : ew->core.height;
576 round_size_to_char(ew->emacs_frame.frame, width, height,
577 &ok_width_int, &ok_height_int);
578 ok_width = (Dimension) ok_width_int;
579 ok_height = (Dimension) ok_height_int;
580 if (ew->emacs_frame.preferred_width)
581 ok_width = ew->emacs_frame.preferred_width;
582 if (ew->emacs_frame.preferred_height)
583 ok_height = ew->emacs_frame.preferred_height;
584 result->request_mode |= CWWidth | CWHeight;
585 result->width = ok_width;
586 result->height = ok_height;
587 if (((mask & CWWidth) && ok_width != request->width)
588 || ((mask & CWHeight) && ok_height != request->height))
589 return XtGeometryAlmost;
591 return XtGeometryYes;
594 /* Xt string-to-scrollbar-placement converter */
595 /* #### Convert this to a `new-style' converter (See XtAddTypeConverter) */
597 /* This variable cannot be a stack variable. */
598 static unsigned char cvt_string_scrollbar_placement;
601 static void Xt_StringToScrollBarPlacement(XrmValuePtr args, /* unused */
602 Cardinal * num_args, /* unused */
607 char *lowerName = (char *)alloca(strlen((char *)fromVal->addr) + 1);
609 XmuCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr);
610 q = XrmStringToQuark(lowerName);
612 toVal->size = sizeof(cvt_string_scrollbar_placement);
613 toVal->addr = (XPointer) & cvt_string_scrollbar_placement;
615 if (q == XrmStringToQuark("top-left")
616 || q == XrmStringToQuark("top_left"))
617 cvt_string_scrollbar_placement = XtTOP_LEFT;
618 else if (q == XrmStringToQuark("bottom-left")
619 || q == XrmStringToQuark("bottom_left"))
620 cvt_string_scrollbar_placement = XtBOTTOM_LEFT;
621 else if (q == XrmStringToQuark("top-right")
622 || q == XrmStringToQuark("top_right"))
623 cvt_string_scrollbar_placement = XtTOP_RIGHT;
624 else if (q == XrmStringToQuark("bottom-right")
625 || q == XrmStringToQuark("bottom_right"))
626 cvt_string_scrollbar_placement = XtBOTTOM_RIGHT;
628 XtStringConversionWarning(fromVal->addr, "scrollBarPlacement");
634 static void EmacsFrameClassInitialize(void)
636 XtAddConverter(XtRString, XtRScrollBarPlacement,
637 Xt_StringToScrollBarPlacement, NULL, 0);
640 /********************* Special entrypoints *******************/
642 void EmacsFrameRecomputeCellSize(Widget w)
644 EmacsFrame ew = (EmacsFrame) w;
646 struct frame *f = ew->emacs_frame.frame;
648 if (!XtIsSubclass(w, emacsFrameClass))
651 default_face_height_and_width(make_frame(f), &ch, &cw);
652 if (FRAME_X_TOP_LEVEL_FRAME_P(f))
653 x_wm_set_cell_size(FRAME_X_SHELL_WIDGET(f), cw, ch);
656 /* Set the size of the widget to have the number of rows and columns
657 specified. This both causes the X window to change and the
658 internal frame structures to get modified to match. */
660 void EmacsFrameSetCharSize(Widget widget, int columns, int rows)
662 EmacsFrame ew = (EmacsFrame) widget;
663 int pixel_width, pixel_height;
664 struct frame *f = ew->emacs_frame.frame;
667 columns = 3; /* no way buddy */
671 char_to_pixel_size(f, columns, rows, &pixel_width, &pixel_height);
673 if (FRAME_X_TOP_LEVEL_FRAME_P(f))
674 x_wm_set_variable_size(FRAME_X_SHELL_WIDGET(f), columns, rows);
678 XtSetArg(al[0], XtNwidth, pixel_width);
679 XtSetArg(al[1], XtNheight, pixel_height);
680 XtSetValues((Widget) ew, al, countof(al));