Mercurial > hg > xemacs-beta
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 } |