comparison src/EmacsShell-sub.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 0293115a14e9
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 /* Emacs shell widget -- define the two widgets.
2 Copyright (C) 1994, 1995 Sun Microsystems, Inc.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; 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 /* Synched up with: Not in FSF. */
22
23 /* Written by Ben Wing, May, 1994. */
24
25 /*
26 It is rather unfortunate that we have to do this. Blame those
27 short-sighted people who designed the monstrosities known as
28 Xt and ICCCM.
29 */
30
31 /*
32 This widget is not actually Emacs-specific; perhaps there could
33 be a better name than "EmacsShell". What it does is work around
34 a limitation in Xt in correctly dealing with the window-manager
35 size hints with applications that
36
37 (a) dynamically change their window size
38 (b) have a cell size (width-inc and height-inc) other than 1
39
40 and
41
42 (c) cannot predict in advance exactly what size their shell will be
43 (This is the more common situation, when you have a number
44 of widgets, each with their own size ideas)
45
46 This widget assumes that your program contains a fixed "base size"
47 plus some number of cells (e.g. character cells). The WMShell
48 resources "widthInc" and "heightInc" specify the size of a
49 character cell, and the window manager will report the app's
50 size in cells rather than in pixels.
51
52 If you use this widget, do not use the WMShell resources
53 "baseWidth", "baseHeight", "minWidth", or "minHeight".
54 Instead, use "widthCells" and "heightCells" to specify the
55 current size in cells (you must keep this up-to-date),
56 and "minWidthCells" and "minHeightCells" to specify the
57 minimum size in cells.
58
59 Every time that the program issues a size command, the
60 "baseWidth", "baseHeight", "minWidth", and "minHeight" fields
61 of the WM_NORMAL_HINTS property will be updated to stay in
62 line with the resource values specified above. The calculations
63 are done once the desired shell size is known but before the
64 window-manager size-change request is issued. (We must do it
65 at this time because before then we don't know what size we
66 will request, and after the request the deed has already
67 been done.)
68
69 After you change the "baseWidth", "baseHeight", "minWidth",
70 or "minHeight" resources, you need to call
71 EmacsShellUpdateSizeHints() to manually update the size
72 hints, except in the following two circumstances:
73
74 (a) you are about to make a geometry request.
75 (b) you are changing only "baseWidth" and "baseHeight"
76 from within a resize procedure. (In this case,
77 the size hints are already correct.)
78
79 */
80
81 #include <config.h>
82
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <X11/StringDefs.h>
86 #include "xintrinsicp.h"
87 #include <X11/Shell.h>
88 #include <X11/ShellP.h>
89 #include <X11/Vendor.h>
90 #include <X11/VendorP.h>
91 #include "EmacsShellP.h"
92
93 #if defined (DEFINE_TOP_LEVEL_EMACS_SHELL)
94 #define EMACS_SHELL_WIDGET TopLevelEmacsShellWidget
95 #define SUPERCLASS_WIDGET_CLASS topLevelShellWidgetClass
96 #define SUPERCLASS_CLASS_REC topLevelShellClassRec
97 #define EMACS_SHELL_REC TopLevelEmacsShellRec
98 #define EMACS_SHELL_CLASS_REC topLevelEmacsShellClassRec
99 #define EMACS_SHELL_CLASS_REC_TYPE TopLevelEmacsShellClassRec
100 #define EMACS_SHELL_CLASS_NAME "TopLevelEmacsShell"
101 #define EMACS_SHELL_WIDGET_CLASS topLevelEmacsShellWidgetClass
102 #define EMACS_SHELL_UPDATE_SIZE_HINTS TopLevelEmacsShellUpdateSizeHints
103 #elif defined (DEFINE_TRANSIENT_EMACS_SHELL)
104 #define EMACS_SHELL_WIDGET TransientEmacsShellWidget
105 #define SUPERCLASS_WIDGET_CLASS transientShellWidgetClass
106 #define SUPERCLASS_CLASS_REC transientShellClassRec
107 #define EMACS_SHELL_REC TransientEmacsShellRec
108 #define EMACS_SHELL_CLASS_REC transientEmacsShellClassRec
109 #define EMACS_SHELL_CLASS_REC_TYPE TransientEmacsShellClassRec
110 #define EMACS_SHELL_CLASS_NAME "TransientEmacsShell"
111 #define EMACS_SHELL_WIDGET_CLASS transientEmacsShellWidgetClass
112 #define EMACS_SHELL_UPDATE_SIZE_HINTS TransientEmacsShellUpdateSizeHints
113 #else
114 Error. Must define either DEFINE_TOP_LEVEL_EMACS_SHELL or
115 DEFINE_TRANSIENT_EMACS_SHELL.
116 #endif
117
118 typedef struct {
119 XtPointer next_extension;
120 XrmQuark record_type;
121 long version;
122 Cardinal record_size;
123 } GenericClassExtRec;
124
125 static XtGeometryResult RootGeometryManager (Widget gw,
126 XtWidgetGeometry *request, XtWidgetGeometry *reply);
127 static void ChangeManaged (Widget w);
128
129 /* snarfed from Shell.c */
130 #define BIGSIZE ((Dimension)32767)
131
132 static XtResource resources[] = {
133 #define offset(field) XtOffset(EMACS_SHELL_WIDGET, emacs_shell.field)
134 #define coreoffset(field) XtOffset(EMACS_SHELL_WIDGET, core.field)
135 #ifdef LWLIB_USES_MOTIF
136 /* *** BOGOSITY^10! *** The Motif VendorShell fucks around with
137 the default values for X and Y, for no obvious reason. This
138 causes Shell to indicate that the defaults of (0,0) were
139 program-specified, instead of letting the WM do what it wants. */
140 {XtNx, XtCPosition, XtRPosition, sizeof(Position),
141 coreoffset (x), XtRImmediate, (XtPointer)BIGSIZE},
142 {XtNy, XtCPosition, XtRPosition, sizeof(Position),
143 coreoffset (y), XtRImmediate, (XtPointer)BIGSIZE},
144 #endif
145 { XtNwidthCells, XtCWidthCells, XtRInt, sizeof(int),
146 offset (width_cells), XtRImmediate, (XtPointer)0},
147 { XtNheightCells, XtCHeightCells, XtRInt, sizeof(int),
148 offset (height_cells), XtRImmediate, (XtPointer)0},
149 { XtNminWidthCells, XtCMinWidthCells, XtRInt, sizeof(int),
150 offset (min_width_cells), XtRImmediate, (XtPointer)0},
151 { XtNminHeightCells, XtCMinHeightCells, XtRInt, sizeof(int),
152 offset (min_height_cells), XtRImmediate, (XtPointer)0},
153 };
154
155 static CompositeClassExtensionRec compositeClassExtRec = {
156 NULL,
157 NULLQUARK,
158 XtCompositeExtensionVersion,
159 sizeof(CompositeClassExtensionRec),
160 TRUE,
161 };
162
163 static ShellClassExtensionRec shellClassExtRec = {
164 NULL,
165 NULLQUARK,
166 XtShellExtensionVersion,
167 sizeof(ShellClassExtensionRec),
168 RootGeometryManager
169 };
170
171 EMACS_SHELL_CLASS_REC_TYPE EMACS_SHELL_CLASS_REC = {
172 { /*
173 * core_class fields
174 */
175 /* superclass */ (WidgetClass) &SUPERCLASS_CLASS_REC,
176 /* class_name */ EMACS_SHELL_CLASS_NAME,
177 /* size */ sizeof(EMACS_SHELL_REC),
178 /* Class Initializer */ NULL,
179 /* class_part_initialize*/ NULL, /* XtInheritClassPartInitialize, */
180 /* Class init'ed ? */ FALSE,
181 /* initialize */ NULL,
182 /* initialize_notify */ NULL,
183 /* realize */ XtInheritRealize,
184 /* actions */ NULL,
185 /* num_actions */ 0,
186 /* resources */ resources,
187 /* resource_count */ XtNumber (resources),
188 /* xrm_class */ NULLQUARK,
189 /* compress_motion */ FALSE,
190 /* compress_exposure */ TRUE,
191 /* compress_enterleave*/ FALSE,
192 /* visible_interest */ TRUE,
193 /* destroy */ NULL,
194 /* resize */ XtInheritResize,
195 /* expose */ NULL,
196 /* set_values */ NULL, /* XtInheritSetValues, */
197 /* set_values_hook */ NULL,
198 /* set_values_almost */ XtInheritSetValuesAlmost,
199 /* get_values_hook */ NULL,
200 /* accept_focus */ NULL,
201 /* intrinsics version */ XtVersion,
202 /* callback offsets */ NULL,
203 /* tm_table */ NULL,
204 /* query_geometry */ NULL,
205 /* display_accelerator*/ NULL,
206 /* extension */ NULL
207 },{ /* Composite */
208 /* geometry_manager */ XtInheritGeometryManager,
209 /* change_managed */ ChangeManaged,
210 /* insert_child */ XtInheritInsertChild,
211 /* delete_child */ XtInheritDeleteChild,
212 /* extension */ (XtPointer)&compositeClassExtRec
213 },{ /* Shell */
214 /* extension */ (XtPointer)&shellClassExtRec
215 },{ /* WMShell */
216 /* extension */ NULL
217 },{ /* VendorShell */
218 /* extension */ NULL
219 },{ /* TopLevelShell or TransientShell */
220 /* both have exactly one XtPointer here. */
221 /* extension */ NULL
222 },{ /* EmacsShell */
223 0
224 }
225 };
226
227 WidgetClass EMACS_SHELL_WIDGET_CLASS = (WidgetClass) &EMACS_SHELL_CLASS_REC;
228
229 static void
230 update_size_hints_internal (EMACS_SHELL_WIDGET w,
231 int width, int height)
232 {
233 int base_width, base_height;
234 int cell_width, cell_height;
235
236 /* time to update them thar size hints */
237 cell_width = w->wm.size_hints.width_inc;
238 cell_height = w->wm.size_hints.height_inc;
239 base_width = width - cell_width * w->emacs_shell.width_cells;
240 base_height = height - cell_height * w->emacs_shell.height_cells;
241 #ifdef DEBUG_GEOMETRY_MANAGEMENT
242 /* Very useful info when debugging geometry management problems.
243 When it's guaranteed that no more such problems exist, take
244 this stuff out. */
245 printf ("update_size_hints_internal:\n");
246 printf (" actual pixel size: %d %d\n", width, height);
247 printf (" cell size in pixels: %d %d\n", cell_width, cell_height);
248 printf (" text area size in cells: %d %d\n", w->emacs_shell.width_cells,
249 w->emacs_shell.height_cells);
250 printf (" base size set to: %d %d\n", base_width, base_height);
251 fflush (stdout);
252 #endif
253 XtVaSetValues ((Widget) w,
254 XtNbaseWidth, base_width,
255 XtNbaseHeight, base_height,
256 XtNminWidth, base_width +
257 cell_width * w->emacs_shell.min_width_cells,
258 XtNminHeight, base_height +
259 cell_height * w->emacs_shell.min_height_cells,
260 NULL);
261 }
262
263 static XtGeometryResult SuperClassRootGeometryManager (gw, request, reply)
264 Widget gw;
265 XtWidgetGeometry *request, *reply;
266 {
267 ShellWidgetClass swc = (ShellWidgetClass) SUPERCLASS_WIDGET_CLASS;
268 ShellClassExtensionRec *scer;
269 GenericClassExtRec *gcer;
270
271 /* find the shell extension record that specifies the
272 root geometry manager method */
273 for (gcer = (GenericClassExtRec *) swc->shell_class.extension;
274 gcer;
275 gcer = (GenericClassExtRec *) gcer->next_extension)
276 {
277 if (gcer->record_type == NULLQUARK)
278 break;
279 }
280
281 if (!gcer)
282 abort ();
283
284 /* call it to actually make the geometry request */
285 scer = (ShellClassExtensionRec *) gcer;
286 return (scer->root_geometry_manager)(gw, request, reply);
287 }
288
289 static XtGeometryResult RootGeometryManager (gw, request, reply)
290 Widget gw;
291 XtWidgetGeometry *request, *reply;
292 {
293 EMACS_SHELL_WIDGET w = (EMACS_SHELL_WIDGET) gw;
294 /* OK since this file is not dumped */
295 static int reentrant = 0;
296 XtGeometryResult result;
297
298 if (reentrant)
299 abort ();
300 reentrant++;
301
302 #ifdef DEBUG_GEOMETRY_MANAGEMENT
303 printf ("root_geometry_manager:\n");
304 printf (" current shell size: %d %d\n", w->core.width, w->core.height);
305 if (request->request_mode & CWWidth)
306 printf ("width requested;");
307 if (request->request_mode & CWHeight)
308 printf ("height requested;");
309 printf ("\n");
310 printf (" requested shell size: %d %d\n", request->width, request->height);
311 #endif
312 /* update the size hints */
313 update_size_hints_internal (w,
314 request->request_mode & CWWidth ?
315 request->width : w->core.width,
316 request->request_mode & CWHeight ?
317 request->height : w->core.height);
318
319 result = SuperClassRootGeometryManager (gw, request, reply);
320
321 #ifdef DEBUG_GEOMETRY_MANAGEMENT
322 printf (" result: %s\n",
323 result == XtGeometryYes ? "XtGeometryYes" :
324 result == XtGeometryNo ? "XtGeometryNo" :
325 result == XtGeometryAlmost ? "XtGeometryAlmost" :
326 "XtGeometryDone");
327 if (reply->request_mode & CWWidth)
328 printf ("width returned;");
329 if (reply->request_mode & CWHeight)
330 printf ("height returned;");
331 printf ("\n");
332 printf (" resulting shell size: %d %d\n", reply->width, reply->height);
333 printf ("----------\n");
334 fflush (stdout);
335 #endif
336 reentrant--;
337 return result;
338 }
339
340 static void
341 ChangeManaged (Widget wid)
342 {
343 EMACS_SHELL_WIDGET w = (EMACS_SHELL_WIDGET) wid;
344
345 /* If not realized, then we're being called from XtRealizeWidget().
346 RootGeometryManager() has not yet been called, and thus our
347 base size is incorrect. We need to set it now or the Shell
348 will mess up geometry specifications with negative positional
349 offsets. */
350 if (!XtIsRealized (wid))
351 {
352 Widget child = NULL;
353 int i;
354
355 /* the managed child indicates what our size is */
356 for (i = 0; i < w->composite.num_children; i++) {
357 if (XtIsManaged(w->composite.children[i])) {
358 child = w->composite.children[i];
359 break;
360 }
361 }
362
363 update_size_hints_internal (w, child->core.width, child->core.height);
364 }
365
366 /* call the real ChangeManaged */
367 (((ShellWidgetClass) SUPERCLASS_WIDGET_CLASS)->
368 composite_class.change_managed)(wid);
369 }
370
371
372 /******************* external entry points *********************/
373
374 void
375 EMACS_SHELL_UPDATE_SIZE_HINTS (Widget gw)
376 {
377 EMACS_SHELL_WIDGET w = (EMACS_SHELL_WIDGET) gw;
378 update_size_hints_internal (w, w->core.width, w->core.height);
379 }