Parent Directory | Revision Log | Patch
revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC | revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC | |
---|---|---|
# | Line 1 | Line 1 |
1 | /* $Header$ */ | /* $Header$ */ |
2 | ||
3 | /* | /* |
4 | * tkGrid.c -- | * tkGrid.c -- |
5 | * | * |
6 | * Grid based geometry manager. | * Grid based geometry manager. |
7 | * | * |
8 | * Copyright (c) 1996-1997 by Sun Microsystems, Inc. | * Copyright (c) 1996-1997 by Sun Microsystems, Inc. |
9 | * | * |
10 | * See the file "license.terms" for information on usage and redistribution | * See the file "license.terms" for information on usage and redistribution |
11 | * of this file, and for a DISCLAIMER OF ALL WARRANTIES. | * of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
12 | * | * |
13 | * RCS: @(#) $Id: tkgrid.c,v 1.1.1.1 2001/06/13 05:02:05 dtashley Exp $ | * RCS: @(#) $Id: tkgrid.c,v 1.1.1.1 2001/06/13 05:02:05 dtashley Exp $ |
14 | */ | */ |
15 | ||
16 | #include "tkInt.h" | #include "tkInt.h" |
17 | ||
18 | /* | /* |
19 | * Convenience Macros | * Convenience Macros |
20 | */ | */ |
21 | ||
22 | #ifdef MAX | #ifdef MAX |
23 | # undef MAX | # undef MAX |
24 | #endif | #endif |
25 | #define MAX(x,y) ((x) > (y) ? (x) : (y)) | #define MAX(x,y) ((x) > (y) ? (x) : (y)) |
26 | #ifdef MIN | #ifdef MIN |
27 | # undef MIN | # undef MIN |
28 | #endif | #endif |
29 | #define MIN(x,y) ((x) > (y) ? (y) : (x)) | #define MIN(x,y) ((x) > (y) ? (y) : (x)) |
30 | ||
31 | #define COLUMN (1) /* working on column offsets */ | #define COLUMN (1) /* working on column offsets */ |
32 | #define ROW (2) /* working on row offsets */ | #define ROW (2) /* working on row offsets */ |
33 | ||
34 | #define CHECK_ONLY (1) /* check max slot constraint */ | #define CHECK_ONLY (1) /* check max slot constraint */ |
35 | #define CHECK_SPACE (2) /* alloc more space, don't change max */ | #define CHECK_SPACE (2) /* alloc more space, don't change max */ |
36 | ||
37 | /* | /* |
38 | * Pre-allocate enough row and column slots for "typical" sized tables | * Pre-allocate enough row and column slots for "typical" sized tables |
39 | * this value should be chosen so by the time the extra malloc's are | * this value should be chosen so by the time the extra malloc's are |
40 | * required, the layout calculations overwehlm them. [A "slot" contains | * required, the layout calculations overwehlm them. [A "slot" contains |
41 | * information for either a row or column, depending upon the context.] | * information for either a row or column, depending upon the context.] |
42 | */ | */ |
43 | ||
44 | #define TYPICAL_SIZE 25 /* (arbitrary guess) */ | #define TYPICAL_SIZE 25 /* (arbitrary guess) */ |
45 | #define PREALLOC 10 /* extra slots to allocate */ | #define PREALLOC 10 /* extra slots to allocate */ |
46 | ||
47 | /* | /* |
48 | * Data structures are allocated dynamically to support arbitrary sized tables. | * Data structures are allocated dynamically to support arbitrary sized tables. |
49 | * However, the space is proportional to the highest numbered slot with | * However, the space is proportional to the highest numbered slot with |
50 | * some non-default property. This limit is used to head off mistakes and | * some non-default property. This limit is used to head off mistakes and |
51 | * denial of service attacks by limiting the amount of storage required. | * denial of service attacks by limiting the amount of storage required. |
52 | */ | */ |
53 | ||
54 | #define MAX_ELEMENT 10000 | #define MAX_ELEMENT 10000 |
55 | ||
56 | /* | /* |
57 | * Special characters to support relative layouts. | * Special characters to support relative layouts. |
58 | */ | */ |
59 | ||
60 | #define REL_SKIP 'x' /* Skip this column. */ | #define REL_SKIP 'x' /* Skip this column. */ |
61 | #define REL_HORIZ '-' /* Extend previous widget horizontally. */ | #define REL_HORIZ '-' /* Extend previous widget horizontally. */ |
62 | #define REL_VERT '^' /* Extend widget from row above. */ | #define REL_VERT '^' /* Extend widget from row above. */ |
63 | ||
64 | /* | /* |
65 | * Structure to hold information for grid masters. A slot is either | * Structure to hold information for grid masters. A slot is either |
66 | * a row or column. | * a row or column. |
67 | */ | */ |
68 | ||
69 | typedef struct SlotInfo { | typedef struct SlotInfo { |
70 | int minSize; /* The minimum size of this slot (in pixels). | int minSize; /* The minimum size of this slot (in pixels). |
71 | * It is set via the rowconfigure or | * It is set via the rowconfigure or |
72 | * columnconfigure commands. */ | * columnconfigure commands. */ |
73 | int weight; /* The resize weight of this slot. (0) means | int weight; /* The resize weight of this slot. (0) means |
74 | * this slot doesn't resize. Extra space in | * this slot doesn't resize. Extra space in |
75 | * the layout is given distributed among slots | * the layout is given distributed among slots |
76 | * inproportion to their weights. */ | * inproportion to their weights. */ |
77 | int pad; /* Extra padding, in pixels, required for | int pad; /* Extra padding, in pixels, required for |
78 | * this slot. This amount is "added" to the | * this slot. This amount is "added" to the |
79 | * largest slave in the slot. */ | * largest slave in the slot. */ |
80 | int offset; /* This is a cached value used for | int offset; /* This is a cached value used for |
81 | * introspection. It is the pixel | * introspection. It is the pixel |
82 | * offset of the right or bottom edge | * offset of the right or bottom edge |
83 | * of this slot from the beginning of the | * of this slot from the beginning of the |
84 | * layout. */ | * layout. */ |
85 | int temp; /* This is a temporary value used for | int temp; /* This is a temporary value used for |
86 | * calculating adjusted weights when | * calculating adjusted weights when |
87 | * shrinking the layout below its | * shrinking the layout below its |
88 | * nominal size. */ | * nominal size. */ |
89 | } SlotInfo; | } SlotInfo; |
90 | ||
91 | /* | /* |
92 | * Structure to hold information during layout calculations. There | * Structure to hold information during layout calculations. There |
93 | * is one of these for each slot, an array for each of the rows or columns. | * is one of these for each slot, an array for each of the rows or columns. |
94 | */ | */ |
95 | ||
96 | typedef struct GridLayout { | typedef struct GridLayout { |
97 | struct Gridder *binNextPtr; /* The next slave window in this bin. | struct Gridder *binNextPtr; /* The next slave window in this bin. |
98 | * Each bin contains a list of all | * Each bin contains a list of all |
99 | * slaves whose spans are >1 and whose | * slaves whose spans are >1 and whose |
100 | * right edges fall in this slot. */ | * right edges fall in this slot. */ |
101 | int minSize; /* Minimum size needed for this slot, | int minSize; /* Minimum size needed for this slot, |
102 | * in pixels. This is the space required | * in pixels. This is the space required |
103 | * to hold any slaves contained entirely | * to hold any slaves contained entirely |
104 | * in this slot, adjusted for any slot | * in this slot, adjusted for any slot |
105 | * constrants, such as size or padding. */ | * constrants, such as size or padding. */ |
106 | int pad; /* Padding needed for this slot */ | int pad; /* Padding needed for this slot */ |
107 | int weight; /* Slot weight, controls resizing. */ | int weight; /* Slot weight, controls resizing. */ |
108 | int minOffset; /* The minimum offset, in pixels, from | int minOffset; /* The minimum offset, in pixels, from |
109 | * the beginning of the layout to the | * the beginning of the layout to the |
110 | * right/bottom edge of the slot calculated | * right/bottom edge of the slot calculated |
111 | * from top/left to bottom/right. */ | * from top/left to bottom/right. */ |
112 | int maxOffset; /* The maximum offset, in pixels, from | int maxOffset; /* The maximum offset, in pixels, from |
113 | * the beginning of the layout to the | * the beginning of the layout to the |
114 | * right-or-bottom edge of the slot calculated | * right-or-bottom edge of the slot calculated |
115 | * from bottom-or-right to top-or-left. */ | * from bottom-or-right to top-or-left. */ |
116 | } GridLayout; | } GridLayout; |
117 | ||
118 | /* | /* |
119 | * Keep one of these for each geometry master. | * Keep one of these for each geometry master. |
120 | */ | */ |
121 | ||
122 | typedef struct { | typedef struct { |
123 | SlotInfo *columnPtr; /* Pointer to array of column constraints. */ | SlotInfo *columnPtr; /* Pointer to array of column constraints. */ |
124 | SlotInfo *rowPtr; /* Pointer to array of row constraints. */ | SlotInfo *rowPtr; /* Pointer to array of row constraints. */ |
125 | int columnEnd; /* The last column occupied by any slave. */ | int columnEnd; /* The last column occupied by any slave. */ |
126 | int columnMax; /* The number of columns with constraints. */ | int columnMax; /* The number of columns with constraints. */ |
127 | int columnSpace; /* The number of slots currently allocated for | int columnSpace; /* The number of slots currently allocated for |
128 | * column constraints. */ | * column constraints. */ |
129 | int rowEnd; /* The last row occupied by any slave. */ | int rowEnd; /* The last row occupied by any slave. */ |
130 | int rowMax; /* The number of rows with constraints. */ | int rowMax; /* The number of rows with constraints. */ |
131 | int rowSpace; /* The number of slots currently allocated | int rowSpace; /* The number of slots currently allocated |
132 | * for row constraints. */ | * for row constraints. */ |
133 | int startX; /* Pixel offset of this layout within its | int startX; /* Pixel offset of this layout within its |
134 | * parent. */ | * parent. */ |
135 | int startY; /* Pixel offset of this layout within its | int startY; /* Pixel offset of this layout within its |
136 | * parent. */ | * parent. */ |
137 | } GridMaster; | } GridMaster; |
138 | ||
139 | /* | /* |
140 | * For each window that the grid cares about (either because | * For each window that the grid cares about (either because |
141 | * the window is managed by the grid or because the window | * the window is managed by the grid or because the window |
142 | * has slaves that are managed by the grid), there is a | * has slaves that are managed by the grid), there is a |
143 | * structure of the following type: | * structure of the following type: |
144 | */ | */ |
145 | ||
146 | typedef struct Gridder { | typedef struct Gridder { |
147 | Tk_Window tkwin; /* Tk token for window. NULL means that | Tk_Window tkwin; /* Tk token for window. NULL means that |
148 | * the window has been deleted, but the | * the window has been deleted, but the |
149 | * gridder hasn't had a chance to clean up | * gridder hasn't had a chance to clean up |
150 | * yet because the structure is still in | * yet because the structure is still in |
151 | * use. */ | * use. */ |
152 | struct Gridder *masterPtr; /* Master window within which this window | struct Gridder *masterPtr; /* Master window within which this window |
153 | * is managed (NULL means this window | * is managed (NULL means this window |
154 | * isn't managed by the gridder). */ | * isn't managed by the gridder). */ |
155 | struct Gridder *nextPtr; /* Next window managed within same | struct Gridder *nextPtr; /* Next window managed within same |
156 | * parent. List order doesn't matter. */ | * parent. List order doesn't matter. */ |
157 | struct Gridder *slavePtr; /* First in list of slaves managed | struct Gridder *slavePtr; /* First in list of slaves managed |
158 | * inside this window (NULL means | * inside this window (NULL means |
159 | * no grid slaves). */ | * no grid slaves). */ |
160 | GridMaster *masterDataPtr; /* Additional data for geometry master. */ | GridMaster *masterDataPtr; /* Additional data for geometry master. */ |
161 | int column, row; /* Location in the grid (starting | int column, row; /* Location in the grid (starting |
162 | * from zero). */ | * from zero). */ |
163 | int numCols, numRows; /* Number of columns or rows this slave spans. | int numCols, numRows; /* Number of columns or rows this slave spans. |
164 | * Should be at least 1. */ | * Should be at least 1. */ |
165 | int padX, padY; /* Total additional pixels to leave around the | int padX, padY; /* Total additional pixels to leave around the |
166 | * window (half of this space is left on each | * window (half of this space is left on each |
167 | * side). This is space *outside* the window: | * side). This is space *outside* the window: |
168 | * we'll allocate extra space in frame but | * we'll allocate extra space in frame but |
169 | * won't enlarge window). */ | * won't enlarge window). */ |
170 | int iPadX, iPadY; /* Total extra pixels to allocate inside the | int iPadX, iPadY; /* Total extra pixels to allocate inside the |
171 | * window (half this amount will appear on | * window (half this amount will appear on |
172 | * each side). */ | * each side). */ |
173 | int sticky; /* which sides of its cavity this window | int sticky; /* which sides of its cavity this window |
174 | * sticks to. See below for definitions */ | * sticks to. See below for definitions */ |
175 | int doubleBw; /* Twice the window's last known border | int doubleBw; /* Twice the window's last known border |
176 | * width. If this changes, the window | * width. If this changes, the window |
177 | * must be re-arranged within its parent. */ | * must be re-arranged within its parent. */ |
178 | int *abortPtr; /* If non-NULL, it means that there is a nested | int *abortPtr; /* If non-NULL, it means that there is a nested |
179 | * call to ArrangeGrid already working on | * call to ArrangeGrid already working on |
180 | * this window. *abortPtr may be set to 1 to | * this window. *abortPtr may be set to 1 to |
181 | * abort that nested call. This happens, for | * abort that nested call. This happens, for |
182 | * example, if tkwin or any of its slaves | * example, if tkwin or any of its slaves |
183 | * is deleted. */ | * is deleted. */ |
184 | int flags; /* Miscellaneous flags; see below | int flags; /* Miscellaneous flags; see below |
185 | * for definitions. */ | * for definitions. */ |
186 | ||
187 | /* | /* |
188 | * These fields are used temporarily for layout calculations only. | * These fields are used temporarily for layout calculations only. |
189 | */ | */ |
190 | ||
191 | struct Gridder *binNextPtr; /* Link to next span>1 slave in this bin. */ | struct Gridder *binNextPtr; /* Link to next span>1 slave in this bin. */ |
192 | int size; /* Nominal size (width or height) in pixels | int size; /* Nominal size (width or height) in pixels |
193 | * of the slave. This includes the padding. */ | * of the slave. This includes the padding. */ |
194 | } Gridder; | } Gridder; |
195 | ||
196 | /* Flag values for "sticky"ness The 16 combinations subsume the packer's | /* Flag values for "sticky"ness The 16 combinations subsume the packer's |
197 | * notion of anchor and fill. | * notion of anchor and fill. |
198 | * | * |
199 | * STICK_NORTH This window sticks to the top of its cavity. | * STICK_NORTH This window sticks to the top of its cavity. |
200 | * STICK_EAST This window sticks to the right edge of its cavity. | * STICK_EAST This window sticks to the right edge of its cavity. |
201 | * STICK_SOUTH This window sticks to the bottom of its cavity. | * STICK_SOUTH This window sticks to the bottom of its cavity. |
202 | * STICK_WEST This window sticks to the left edge of its cavity. | * STICK_WEST This window sticks to the left edge of its cavity. |
203 | */ | */ |
204 | ||
205 | #define STICK_NORTH 1 | #define STICK_NORTH 1 |
206 | #define STICK_EAST 2 | #define STICK_EAST 2 |
207 | #define STICK_SOUTH 4 | #define STICK_SOUTH 4 |
208 | #define STICK_WEST 8 | #define STICK_WEST 8 |
209 | ||
210 | /* | /* |
211 | * Flag values for Grid structures: | * Flag values for Grid structures: |
212 | * | * |
213 | * REQUESTED_RELAYOUT: 1 means a Tcl_DoWhenIdle request | * REQUESTED_RELAYOUT: 1 means a Tcl_DoWhenIdle request |
214 | * has already been made to re-arrange | * has already been made to re-arrange |
215 | * all the slaves of this window. | * all the slaves of this window. |
216 | * | * |
217 | * DONT_PROPAGATE: 1 means don't set this window's requested | * DONT_PROPAGATE: 1 means don't set this window's requested |
218 | * size. 0 means if this window is a master | * size. 0 means if this window is a master |
219 | * then Tk will set its requested size to fit | * then Tk will set its requested size to fit |
220 | * the needs of its slaves. | * the needs of its slaves. |
221 | */ | */ |
222 | ||
223 | #define REQUESTED_RELAYOUT 1 | #define REQUESTED_RELAYOUT 1 |
224 | #define DONT_PROPAGATE 2 | #define DONT_PROPAGATE 2 |
225 | ||
226 | /* | /* |
227 | * Prototypes for procedures used only in this file: | * Prototypes for procedures used only in this file: |
228 | */ | */ |
229 | ||
230 | static void AdjustForSticky _ANSI_ARGS_((Gridder *slavePtr, int *xPtr, | static void AdjustForSticky _ANSI_ARGS_((Gridder *slavePtr, int *xPtr, |
231 | int *yPtr, int *widthPtr, int *heightPtr)); | int *yPtr, int *widthPtr, int *heightPtr)); |
232 | static int AdjustOffsets _ANSI_ARGS_((int width, | static int AdjustOffsets _ANSI_ARGS_((int width, |
233 | int elements, SlotInfo *slotPtr)); | int elements, SlotInfo *slotPtr)); |
234 | static void ArrangeGrid _ANSI_ARGS_((ClientData clientData)); | static void ArrangeGrid _ANSI_ARGS_((ClientData clientData)); |
235 | static int CheckSlotData _ANSI_ARGS_((Gridder *masterPtr, int slot, | static int CheckSlotData _ANSI_ARGS_((Gridder *masterPtr, int slot, |
236 | int slotType, int checkOnly)); | int slotType, int checkOnly)); |
237 | static int ConfigureSlaves _ANSI_ARGS_((Tcl_Interp *interp, | static int ConfigureSlaves _ANSI_ARGS_((Tcl_Interp *interp, |
238 | Tk_Window tkwin, int argc, char *argv[])); | Tk_Window tkwin, int argc, char *argv[])); |
239 | static void DestroyGrid _ANSI_ARGS_((char *memPtr)); | static void DestroyGrid _ANSI_ARGS_((char *memPtr)); |
240 | static Gridder *GetGrid _ANSI_ARGS_((Tk_Window tkwin)); | static Gridder *GetGrid _ANSI_ARGS_((Tk_Window tkwin)); |
241 | static void GridStructureProc _ANSI_ARGS_(( | static void GridStructureProc _ANSI_ARGS_(( |
242 | ClientData clientData, XEvent *eventPtr)); | ClientData clientData, XEvent *eventPtr)); |
243 | static void GridLostSlaveProc _ANSI_ARGS_((ClientData clientData, | static void GridLostSlaveProc _ANSI_ARGS_((ClientData clientData, |
244 | Tk_Window tkwin)); | Tk_Window tkwin)); |
245 | static void GridReqProc _ANSI_ARGS_((ClientData clientData, | static void GridReqProc _ANSI_ARGS_((ClientData clientData, |
246 | Tk_Window tkwin)); | Tk_Window tkwin)); |
247 | static void InitMasterData _ANSI_ARGS_((Gridder *masterPtr)); | static void InitMasterData _ANSI_ARGS_((Gridder *masterPtr)); |
248 | static int ResolveConstraints _ANSI_ARGS_((Gridder *gridPtr, | static int ResolveConstraints _ANSI_ARGS_((Gridder *gridPtr, |
249 | int rowOrColumn, int maxOffset)); | int rowOrColumn, int maxOffset)); |
250 | static void SetGridSize _ANSI_ARGS_((Gridder *gridPtr)); | static void SetGridSize _ANSI_ARGS_((Gridder *gridPtr)); |
251 | static void StickyToString _ANSI_ARGS_((int flags, char *result)); | static void StickyToString _ANSI_ARGS_((int flags, char *result)); |
252 | static int StringToSticky _ANSI_ARGS_((char *string)); | static int StringToSticky _ANSI_ARGS_((char *string)); |
253 | static void Unlink _ANSI_ARGS_((Gridder *gridPtr)); | static void Unlink _ANSI_ARGS_((Gridder *gridPtr)); |
254 | ||
255 | static Tk_GeomMgr gridMgrType = { | static Tk_GeomMgr gridMgrType = { |
256 | "grid", /* name */ | "grid", /* name */ |
257 | GridReqProc, /* requestProc */ | GridReqProc, /* requestProc */ |
258 | GridLostSlaveProc, /* lostSlaveProc */ | GridLostSlaveProc, /* lostSlaveProc */ |
259 | }; | }; |
260 | ||
261 | /* | /* |
262 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
263 | * | * |
264 | * Tk_GridCmd -- | * Tk_GridCmd -- |
265 | * | * |
266 | * This procedure is invoked to process the "grid" Tcl command. | * This procedure is invoked to process the "grid" Tcl command. |
267 | * See the user documentation for details on what it does. | * See the user documentation for details on what it does. |
268 | * | * |
269 | * Results: | * Results: |
270 | * A standard Tcl result. | * A standard Tcl result. |
271 | * | * |
272 | * Side effects: | * Side effects: |
273 | * See the user documentation. | * See the user documentation. |
274 | * | * |
275 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
276 | */ | */ |
277 | ||
278 | int | int |
279 | Tk_GridCmd(clientData, interp, argc, argv) | Tk_GridCmd(clientData, interp, argc, argv) |
280 | ClientData clientData; /* Main window associated with | ClientData clientData; /* Main window associated with |
281 | * interpreter. */ | * interpreter. */ |
282 | Tcl_Interp *interp; /* Current interpreter. */ | Tcl_Interp *interp; /* Current interpreter. */ |
283 | int argc; /* Number of arguments. */ | int argc; /* Number of arguments. */ |
284 | char **argv; /* Argument strings. */ | char **argv; /* Argument strings. */ |
285 | { | { |
286 | Tk_Window tkwin = (Tk_Window) clientData; | Tk_Window tkwin = (Tk_Window) clientData; |
287 | Gridder *masterPtr; /* master grid record */ | Gridder *masterPtr; /* master grid record */ |
288 | GridMaster *gridPtr; /* pointer to grid data */ | GridMaster *gridPtr; /* pointer to grid data */ |
289 | size_t length; /* streing length of argument */ | size_t length; /* streing length of argument */ |
290 | char c; /* 1st character of argument */ | char c; /* 1st character of argument */ |
291 | ||
292 | if ((argc >= 2) && ((argv[1][0] == '.') || (argv[1][0] == REL_SKIP) || | if ((argc >= 2) && ((argv[1][0] == '.') || (argv[1][0] == REL_SKIP) || |
293 | (argv[1][0] == REL_VERT))) { | (argv[1][0] == REL_VERT))) { |
294 | return ConfigureSlaves(interp, tkwin, argc-1, argv+1); | return ConfigureSlaves(interp, tkwin, argc-1, argv+1); |
295 | } | } |
296 | if (argc < 3) { | if (argc < 3) { |
297 | Tcl_AppendResult(interp, "wrong # args: should be \"", | Tcl_AppendResult(interp, "wrong # args: should be \"", |
298 | argv[0], " option arg ?arg ...?\"", (char *) NULL); | argv[0], " option arg ?arg ...?\"", (char *) NULL); |
299 | return TCL_ERROR; | return TCL_ERROR; |
300 | } | } |
301 | c = argv[1][0]; | c = argv[1][0]; |
302 | length = strlen(argv[1]); | length = strlen(argv[1]); |
303 | ||
304 | if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) { | if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) { |
305 | Tk_Window master; | Tk_Window master; |
306 | int row, column; /* origin for bounding box */ | int row, column; /* origin for bounding box */ |
307 | int row2, column2; /* end of bounding box */ | int row2, column2; /* end of bounding box */ |
308 | int endX, endY; /* last column/row in the layout */ | int endX, endY; /* last column/row in the layout */ |
309 | int x=0, y=0; /* starting pixels for this bounding box */ | int x=0, y=0; /* starting pixels for this bounding box */ |
310 | int width, height; /* size of the bounding box */ | int width, height; /* size of the bounding box */ |
311 | char buf[TCL_INTEGER_SPACE * 4]; | char buf[TCL_INTEGER_SPACE * 4]; |
312 | ||
313 | if (argc!=3 && argc != 5 && argc != 7) { | if (argc!=3 && argc != 5 && argc != 7) { |
314 | Tcl_AppendResult(interp, "wrong number of arguments: ", | Tcl_AppendResult(interp, "wrong number of arguments: ", |
315 | "must be \"",argv[0], | "must be \"",argv[0], |
316 | " bbox master ?column row ?column row??\"", | " bbox master ?column row ?column row??\"", |
317 | (char *) NULL); | (char *) NULL); |
318 | return TCL_ERROR; | return TCL_ERROR; |
319 | } | } |
320 | ||
321 | master = Tk_NameToWindow(interp, argv[2], tkwin); | master = Tk_NameToWindow(interp, argv[2], tkwin); |
322 | if (master == NULL) { | if (master == NULL) { |
323 | return TCL_ERROR; | return TCL_ERROR; |
324 | } | } |
325 | masterPtr = GetGrid(master); | masterPtr = GetGrid(master); |
326 | ||
327 | if (argc >= 5) { | if (argc >= 5) { |
328 | if (Tcl_GetInt(interp, argv[3], &column) != TCL_OK) { | if (Tcl_GetInt(interp, argv[3], &column) != TCL_OK) { |
329 | return TCL_ERROR; | return TCL_ERROR; |
330 | } | } |
331 | if (Tcl_GetInt(interp, argv[4], &row) != TCL_OK) { | if (Tcl_GetInt(interp, argv[4], &row) != TCL_OK) { |
332 | return TCL_ERROR; | return TCL_ERROR; |
333 | } | } |
334 | column2 = column; | column2 = column; |
335 | row2 = row; | row2 = row; |
336 | } | } |
337 | ||
338 | if (argc == 7) { | if (argc == 7) { |
339 | if (Tcl_GetInt(interp, argv[5], &column2) != TCL_OK) { | if (Tcl_GetInt(interp, argv[5], &column2) != TCL_OK) { |
340 | return TCL_ERROR; | return TCL_ERROR; |
341 | } | } |
342 | if (Tcl_GetInt(interp, argv[6], &row2) != TCL_OK) { | if (Tcl_GetInt(interp, argv[6], &row2) != TCL_OK) { |
343 | return TCL_ERROR; | return TCL_ERROR; |
344 | } | } |
345 | } | } |
346 | ||
347 | gridPtr = masterPtr->masterDataPtr; | gridPtr = masterPtr->masterDataPtr; |
348 | if (gridPtr == NULL) { | if (gridPtr == NULL) { |
349 | Tcl_SetResult(interp, "0 0 0 0", TCL_STATIC); | Tcl_SetResult(interp, "0 0 0 0", TCL_STATIC); |
350 | return(TCL_OK); | return(TCL_OK); |
351 | } | } |
352 | ||
353 | SetGridSize(masterPtr); | SetGridSize(masterPtr); |
354 | endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); | endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); |
355 | endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); | endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); |
356 | ||
357 | if ((endX == 0) || (endY == 0)) { | if ((endX == 0) || (endY == 0)) { |
358 | Tcl_SetResult(interp, "0 0 0 0", TCL_STATIC); | Tcl_SetResult(interp, "0 0 0 0", TCL_STATIC); |
359 | return(TCL_OK); | return(TCL_OK); |
360 | } | } |
361 | if (argc == 3) { | if (argc == 3) { |
362 | row = column = 0; | row = column = 0; |
363 | row2 = endY; | row2 = endY; |
364 | column2 = endX; | column2 = endX; |
365 | } | } |
366 | ||
367 | if (column > column2) { | if (column > column2) { |
368 | int temp = column; | int temp = column; |
369 | column = column2, column2 = temp; | column = column2, column2 = temp; |
370 | } | } |
371 | if (row > row2) { | if (row > row2) { |
372 | int temp = row; | int temp = row; |
373 | row = row2, row2 = temp; | row = row2, row2 = temp; |
374 | } | } |
375 | ||
376 | if (column > 0 && column < endX) { | if (column > 0 && column < endX) { |
377 | x = gridPtr->columnPtr[column-1].offset; | x = gridPtr->columnPtr[column-1].offset; |
378 | } else if (column > 0) { | } else if (column > 0) { |
379 | x = gridPtr->columnPtr[endX-1].offset; | x = gridPtr->columnPtr[endX-1].offset; |
380 | } | } |
381 | ||
382 | if (row > 0 && row < endY) { | if (row > 0 && row < endY) { |
383 | y = gridPtr->rowPtr[row-1].offset; | y = gridPtr->rowPtr[row-1].offset; |
384 | } else if (row > 0) { | } else if (row > 0) { |
385 | y = gridPtr->rowPtr[endY-1].offset; | y = gridPtr->rowPtr[endY-1].offset; |
386 | } | } |
387 | ||
388 | if (column2 < 0) { | if (column2 < 0) { |
389 | width = 0; | width = 0; |
390 | } else if (column2 >= endX) { | } else if (column2 >= endX) { |
391 | width = gridPtr->columnPtr[endX-1].offset - x; | width = gridPtr->columnPtr[endX-1].offset - x; |
392 | } else { | } else { |
393 | width = gridPtr->columnPtr[column2].offset - x; | width = gridPtr->columnPtr[column2].offset - x; |
394 | } | } |
395 | ||
396 | if (row2 < 0) { | if (row2 < 0) { |
397 | height = 0; | height = 0; |
398 | } else if (row2 >= endY) { | } else if (row2 >= endY) { |
399 | height = gridPtr->rowPtr[endY-1].offset - y; | height = gridPtr->rowPtr[endY-1].offset - y; |
400 | } else { | } else { |
401 | height = gridPtr->rowPtr[row2].offset - y; | height = gridPtr->rowPtr[row2].offset - y; |
402 | } | } |
403 | ||
404 | sprintf(buf, "%d %d %d %d", x + gridPtr->startX, y + gridPtr->startY, | sprintf(buf, "%d %d %d %d", x + gridPtr->startX, y + gridPtr->startY, |
405 | width, height); | width, height); |
406 | Tcl_SetResult(interp, buf, TCL_VOLATILE); | Tcl_SetResult(interp, buf, TCL_VOLATILE); |
407 | } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) { | } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) { |
408 | if (argv[2][0] != '.') { | if (argv[2][0] != '.') { |
409 | Tcl_AppendResult(interp, "bad argument \"", argv[2], | Tcl_AppendResult(interp, "bad argument \"", argv[2], |
410 | "\": must be name of window", (char *) NULL); | "\": must be name of window", (char *) NULL); |
411 | return TCL_ERROR; | return TCL_ERROR; |
412 | } | } |
413 | return ConfigureSlaves(interp, tkwin, argc-2, argv+2); | return ConfigureSlaves(interp, tkwin, argc-2, argv+2); |
414 | } else if (((c == 'f') && (strncmp(argv[1], "forget", length) == 0)) || | } else if (((c == 'f') && (strncmp(argv[1], "forget", length) == 0)) || |
415 | ((c == 'r') && (strncmp(argv[1], "remove", length) == 0))) { | ((c == 'r') && (strncmp(argv[1], "remove", length) == 0))) { |
416 | Tk_Window slave; | Tk_Window slave; |
417 | Gridder *slavePtr; | Gridder *slavePtr; |
418 | int i; | int i; |
419 | ||
420 | for (i = 2; i < argc; i++) { | for (i = 2; i < argc; i++) { |
421 | slave = Tk_NameToWindow(interp, argv[i], tkwin); | slave = Tk_NameToWindow(interp, argv[i], tkwin); |
422 | if (slave == NULL) { | if (slave == NULL) { |
423 | return TCL_ERROR; | return TCL_ERROR; |
424 | } | } |
425 | slavePtr = GetGrid(slave); | slavePtr = GetGrid(slave); |
426 | if (slavePtr->masterPtr != NULL) { | if (slavePtr->masterPtr != NULL) { |
427 | ||
428 | /* | /* |
429 | * For "forget", reset all the settings to their defaults | * For "forget", reset all the settings to their defaults |
430 | */ | */ |
431 | ||
432 | if (c == 'f') { | if (c == 'f') { |
433 | slavePtr->column = slavePtr->row = -1; | slavePtr->column = slavePtr->row = -1; |
434 | slavePtr->numCols = 1; | slavePtr->numCols = 1; |
435 | slavePtr->numRows = 1; | slavePtr->numRows = 1; |
436 | slavePtr->padX = slavePtr->padY = 0; | slavePtr->padX = slavePtr->padY = 0; |
437 | slavePtr->iPadX = slavePtr->iPadY = 0; | slavePtr->iPadX = slavePtr->iPadY = 0; |
438 | slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; | slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; |
439 | if (slavePtr->flags & REQUESTED_RELAYOUT) { | if (slavePtr->flags & REQUESTED_RELAYOUT) { |
440 | Tcl_CancelIdleCall(ArrangeGrid, (ClientData) slavePtr); | Tcl_CancelIdleCall(ArrangeGrid, (ClientData) slavePtr); |
441 | } | } |
442 | slavePtr->flags = 0; | slavePtr->flags = 0; |
443 | slavePtr->sticky = 0; | slavePtr->sticky = 0; |
444 | } | } |
445 | Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, | Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, |
446 | (ClientData) NULL); | (ClientData) NULL); |
447 | if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { | if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { |
448 | Tk_UnmaintainGeometry(slavePtr->tkwin, | Tk_UnmaintainGeometry(slavePtr->tkwin, |
449 | slavePtr->masterPtr->tkwin); | slavePtr->masterPtr->tkwin); |
450 | } | } |
451 | Unlink(slavePtr); | Unlink(slavePtr); |
452 | Tk_UnmapWindow(slavePtr->tkwin); | Tk_UnmapWindow(slavePtr->tkwin); |
453 | } | } |
454 | } | } |
455 | } else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) { | } else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) { |
456 | register Gridder *slavePtr; | register Gridder *slavePtr; |
457 | Tk_Window slave; | Tk_Window slave; |
458 | char buffer[64 + TCL_INTEGER_SPACE * 4]; | char buffer[64 + TCL_INTEGER_SPACE * 4]; |
459 | ||
460 | if (argc != 3) { | if (argc != 3) { |
461 | Tcl_AppendResult(interp, "wrong # args: should be \"", | Tcl_AppendResult(interp, "wrong # args: should be \"", |
462 | argv[0], " info window\"", (char *) NULL); | argv[0], " info window\"", (char *) NULL); |
463 | return TCL_ERROR; | return TCL_ERROR; |
464 | } | } |
465 | slave = Tk_NameToWindow(interp, argv[2], tkwin); | slave = Tk_NameToWindow(interp, argv[2], tkwin); |
466 | if (slave == NULL) { | if (slave == NULL) { |
467 | return TCL_ERROR; | return TCL_ERROR; |
468 | } | } |
469 | slavePtr = GetGrid(slave); | slavePtr = GetGrid(slave); |
470 | if (slavePtr->masterPtr == NULL) { | if (slavePtr->masterPtr == NULL) { |
471 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
472 | return TCL_OK; | return TCL_OK; |
473 | } | } |
474 | ||
475 | Tcl_AppendElement(interp, "-in"); | Tcl_AppendElement(interp, "-in"); |
476 | Tcl_AppendElement(interp, Tk_PathName(slavePtr->masterPtr->tkwin)); | Tcl_AppendElement(interp, Tk_PathName(slavePtr->masterPtr->tkwin)); |
477 | sprintf(buffer, " -column %d -row %d -columnspan %d -rowspan %d", | sprintf(buffer, " -column %d -row %d -columnspan %d -rowspan %d", |
478 | slavePtr->column, slavePtr->row, | slavePtr->column, slavePtr->row, |
479 | slavePtr->numCols, slavePtr->numRows); | slavePtr->numCols, slavePtr->numRows); |
480 | Tcl_AppendResult(interp, buffer, (char *) NULL); | Tcl_AppendResult(interp, buffer, (char *) NULL); |
481 | sprintf(buffer, " -ipadx %d -ipady %d -padx %d -pady %d", | sprintf(buffer, " -ipadx %d -ipady %d -padx %d -pady %d", |
482 | slavePtr->iPadX/2, slavePtr->iPadY/2, slavePtr->padX/2, | slavePtr->iPadX/2, slavePtr->iPadY/2, slavePtr->padX/2, |
483 | slavePtr->padY/2); | slavePtr->padY/2); |
484 | Tcl_AppendResult(interp, buffer, (char *) NULL); | Tcl_AppendResult(interp, buffer, (char *) NULL); |
485 | StickyToString(slavePtr->sticky,buffer); | StickyToString(slavePtr->sticky,buffer); |
486 | Tcl_AppendResult(interp, " -sticky ", buffer, (char *) NULL); | Tcl_AppendResult(interp, " -sticky ", buffer, (char *) NULL); |
487 | } else if((c == 'l') && (strncmp(argv[1], "location", length) == 0)) { | } else if((c == 'l') && (strncmp(argv[1], "location", length) == 0)) { |
488 | Tk_Window master; | Tk_Window master; |
489 | register SlotInfo *slotPtr; | register SlotInfo *slotPtr; |
490 | int x, y; /* Offset in pixels, from edge of parent. */ | int x, y; /* Offset in pixels, from edge of parent. */ |
491 | int i, j; /* Corresponding column and row indeces. */ | int i, j; /* Corresponding column and row indeces. */ |
492 | int endX, endY; /* end of grid */ | int endX, endY; /* end of grid */ |
493 | char buf[TCL_INTEGER_SPACE * 2]; | char buf[TCL_INTEGER_SPACE * 2]; |
494 | ||
495 | if (argc != 5) { | if (argc != 5) { |
496 | Tcl_AppendResult(interp, "wrong # args: should be \"", | Tcl_AppendResult(interp, "wrong # args: should be \"", |
497 | argv[0], " location master x y\"", (char *)NULL); | argv[0], " location master x y\"", (char *)NULL); |
498 | return TCL_ERROR; | return TCL_ERROR; |
499 | } | } |
500 | ||
501 | master = Tk_NameToWindow(interp, argv[2], tkwin); | master = Tk_NameToWindow(interp, argv[2], tkwin); |
502 | if (master == NULL) { | if (master == NULL) { |
503 | return TCL_ERROR; | return TCL_ERROR; |
504 | } | } |
505 | ||
506 | if (Tk_GetPixels(interp, master, argv[3], &x) != TCL_OK) { | if (Tk_GetPixels(interp, master, argv[3], &x) != TCL_OK) { |
507 | return TCL_ERROR; | return TCL_ERROR; |
508 | } | } |
509 | if (Tk_GetPixels(interp, master, argv[4], &y) != TCL_OK) { | if (Tk_GetPixels(interp, master, argv[4], &y) != TCL_OK) { |
510 | return TCL_ERROR; | return TCL_ERROR; |
511 | } | } |
512 | ||
513 | masterPtr = GetGrid(master); | masterPtr = GetGrid(master); |
514 | if (masterPtr->masterDataPtr == NULL) { | if (masterPtr->masterDataPtr == NULL) { |
515 | Tcl_SetResult(interp, "-1 -1", TCL_STATIC); | Tcl_SetResult(interp, "-1 -1", TCL_STATIC); |
516 | return TCL_OK; | return TCL_OK; |
517 | } | } |
518 | gridPtr = masterPtr->masterDataPtr; | gridPtr = masterPtr->masterDataPtr; |
519 | ||
520 | /* | /* |
521 | * Update any pending requests. This is not always the | * Update any pending requests. This is not always the |
522 | * steady state value, as more configure events could be in | * steady state value, as more configure events could be in |
523 | * the pipeline, but its as close as its easy to get. | * the pipeline, but its as close as its easy to get. |
524 | */ | */ |
525 | ||
526 | while (masterPtr->flags & REQUESTED_RELAYOUT) { | while (masterPtr->flags & REQUESTED_RELAYOUT) { |
527 | Tcl_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr); | Tcl_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr); |
528 | ArrangeGrid ((ClientData) masterPtr); | ArrangeGrid ((ClientData) masterPtr); |
529 | } | } |
530 | SetGridSize(masterPtr); | SetGridSize(masterPtr); |
531 | endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); | endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); |
532 | endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); | endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); |
533 | ||
534 | slotPtr = masterPtr->masterDataPtr->columnPtr; | slotPtr = masterPtr->masterDataPtr->columnPtr; |
535 | if (x < masterPtr->masterDataPtr->startX) { | if (x < masterPtr->masterDataPtr->startX) { |
536 | i = -1; | i = -1; |
537 | } else { | } else { |
538 | x -= masterPtr->masterDataPtr->startX; | x -= masterPtr->masterDataPtr->startX; |
539 | for (i=0;slotPtr[i].offset < x && i < endX; i++) { | for (i=0;slotPtr[i].offset < x && i < endX; i++) { |
540 | /* null body */ | /* null body */ |
541 | } | } |
542 | } | } |
543 | ||
544 | slotPtr = masterPtr->masterDataPtr->rowPtr; | slotPtr = masterPtr->masterDataPtr->rowPtr; |
545 | if (y < masterPtr->masterDataPtr->startY) { | if (y < masterPtr->masterDataPtr->startY) { |
546 | j = -1; | j = -1; |
547 | } else { | } else { |
548 | y -= masterPtr->masterDataPtr->startY; | y -= masterPtr->masterDataPtr->startY; |
549 | for (j=0;slotPtr[j].offset < y && j < endY; j++) { | for (j=0;slotPtr[j].offset < y && j < endY; j++) { |
550 | /* null body */ | /* null body */ |
551 | } | } |
552 | } | } |
553 | ||
554 | sprintf(buf, "%d %d", i, j); | sprintf(buf, "%d %d", i, j); |
555 | Tcl_SetResult(interp, buf, TCL_VOLATILE); | Tcl_SetResult(interp, buf, TCL_VOLATILE); |
556 | } else if ((c == 'p') && (strncmp(argv[1], "propagate", length) == 0)) { | } else if ((c == 'p') && (strncmp(argv[1], "propagate", length) == 0)) { |
557 | Tk_Window master; | Tk_Window master; |
558 | int propagate; | int propagate; |
559 | ||
560 | if (argc > 4) { | if (argc > 4) { |
561 | Tcl_AppendResult(interp, "wrong # args: should be \"", | Tcl_AppendResult(interp, "wrong # args: should be \"", |
562 | argv[0], " propagate window ?boolean?\"", | argv[0], " propagate window ?boolean?\"", |
563 | (char *) NULL); | (char *) NULL); |
564 | return TCL_ERROR; | return TCL_ERROR; |
565 | } | } |
566 | master = Tk_NameToWindow(interp, argv[2], tkwin); | master = Tk_NameToWindow(interp, argv[2], tkwin); |
567 | if (master == NULL) { | if (master == NULL) { |
568 | return TCL_ERROR; | return TCL_ERROR; |
569 | } | } |
570 | masterPtr = GetGrid(master); | masterPtr = GetGrid(master); |
571 | if (argc == 3) { | if (argc == 3) { |
572 | Tcl_SetResult(interp, | Tcl_SetResult(interp, |
573 | ((masterPtr->flags & DONT_PROPAGATE) ? "0" : "1"), | ((masterPtr->flags & DONT_PROPAGATE) ? "0" : "1"), |
574 | TCL_STATIC); | TCL_STATIC); |
575 | return TCL_OK; | return TCL_OK; |
576 | } | } |
577 | if (Tcl_GetBoolean(interp, argv[3], &propagate) != TCL_OK) { | if (Tcl_GetBoolean(interp, argv[3], &propagate) != TCL_OK) { |
578 | return TCL_ERROR; | return TCL_ERROR; |
579 | } | } |
580 | ||
581 | /* Only request a relayout if the propagation bit changes */ | /* Only request a relayout if the propagation bit changes */ |
582 | ||
583 | if ((!propagate) ^ (masterPtr->flags&DONT_PROPAGATE)) { | if ((!propagate) ^ (masterPtr->flags&DONT_PROPAGATE)) { |
584 | if (propagate) { | if (propagate) { |
585 | masterPtr->flags &= ~DONT_PROPAGATE; | masterPtr->flags &= ~DONT_PROPAGATE; |
586 | } else { | } else { |
587 | masterPtr->flags |= DONT_PROPAGATE; | masterPtr->flags |= DONT_PROPAGATE; |
588 | } | } |
589 | ||
590 | /* | /* |
591 | * Re-arrange the master to allow new geometry information to | * Re-arrange the master to allow new geometry information to |
592 | * propagate upwards to the master's master. | * propagate upwards to the master's master. |
593 | */ | */ |
594 | ||
595 | if (masterPtr->abortPtr != NULL) { | if (masterPtr->abortPtr != NULL) { |
596 | *masterPtr->abortPtr = 1; | *masterPtr->abortPtr = 1; |
597 | } | } |
598 | if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { | if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { |
599 | masterPtr->flags |= REQUESTED_RELAYOUT; | masterPtr->flags |= REQUESTED_RELAYOUT; |
600 | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); |
601 | } | } |
602 | } | } |
603 | } else if ((c == 's') && (strncmp(argv[1], "size", length) == 0) | } else if ((c == 's') && (strncmp(argv[1], "size", length) == 0) |
604 | && (length > 1)) { | && (length > 1)) { |
605 | Tk_Window master; | Tk_Window master; |
606 | ||
607 | if (argc != 3) { | if (argc != 3) { |
608 | Tcl_AppendResult(interp, "wrong # args: should be \"", | Tcl_AppendResult(interp, "wrong # args: should be \"", |
609 | argv[0], " size window\"", (char *) NULL); | argv[0], " size window\"", (char *) NULL); |
610 | return TCL_ERROR; | return TCL_ERROR; |
611 | } | } |
612 | master = Tk_NameToWindow(interp, argv[2], tkwin); | master = Tk_NameToWindow(interp, argv[2], tkwin); |
613 | if (master == NULL) { | if (master == NULL) { |
614 | return TCL_ERROR; | return TCL_ERROR; |
615 | } | } |
616 | masterPtr = GetGrid(master); | masterPtr = GetGrid(master); |
617 | ||
618 | if (masterPtr->masterDataPtr != NULL) { | if (masterPtr->masterDataPtr != NULL) { |
619 | char buf[TCL_INTEGER_SPACE * 2]; | char buf[TCL_INTEGER_SPACE * 2]; |
620 | ||
621 | SetGridSize(masterPtr); | SetGridSize(masterPtr); |
622 | gridPtr = masterPtr->masterDataPtr; | gridPtr = masterPtr->masterDataPtr; |
623 | sprintf(buf, "%d %d", | sprintf(buf, "%d %d", |
624 | MAX(gridPtr->columnEnd, gridPtr->columnMax), | MAX(gridPtr->columnEnd, gridPtr->columnMax), |
625 | MAX(gridPtr->rowEnd, gridPtr->rowMax)); | MAX(gridPtr->rowEnd, gridPtr->rowMax)); |
626 | Tcl_SetResult(interp, buf, TCL_VOLATILE); | Tcl_SetResult(interp, buf, TCL_VOLATILE); |
627 | } else { | } else { |
628 | Tcl_SetResult(interp, "0 0", TCL_STATIC); | Tcl_SetResult(interp, "0 0", TCL_STATIC); |
629 | } | } |
630 | } else if ((c == 's') && (strncmp(argv[1], "slaves", length) == 0) | } else if ((c == 's') && (strncmp(argv[1], "slaves", length) == 0) |
631 | && (length > 1)) { | && (length > 1)) { |
632 | Tk_Window master; | Tk_Window master; |
633 | Gridder *slavePtr; | Gridder *slavePtr; |
634 | int i, value; | int i, value; |
635 | int row = -1, column = -1; | int row = -1, column = -1; |
636 | ||
637 | if ((argc < 3) || ((argc%2) == 0)) { | if ((argc < 3) || ((argc%2) == 0)) { |
638 | Tcl_AppendResult(interp, "wrong # args: should be \"", | Tcl_AppendResult(interp, "wrong # args: should be \"", |
639 | argv[0], " slaves window ?-option value...?\"", | argv[0], " slaves window ?-option value...?\"", |
640 | (char *) NULL); | (char *) NULL); |
641 | return TCL_ERROR; | return TCL_ERROR; |
642 | } | } |
643 | ||
644 | for (i=3; i<argc; i+=2) { | for (i=3; i<argc; i+=2) { |
645 | length = strlen(argv[i]); | length = strlen(argv[i]); |
646 | if ((*argv[i] != '-') || (length < 2)) { | if ((*argv[i] != '-') || (length < 2)) { |
647 | Tcl_AppendResult(interp, "invalid args: should be \"", | Tcl_AppendResult(interp, "invalid args: should be \"", |
648 | argv[0], " slaves window ?-option value...?\"", | argv[0], " slaves window ?-option value...?\"", |
649 | (char *) NULL); | (char *) NULL); |
650 | return TCL_ERROR; | return TCL_ERROR; |
651 | } | } |
652 | if (Tcl_GetInt(interp, argv[i+1], &value) != TCL_OK) { | if (Tcl_GetInt(interp, argv[i+1], &value) != TCL_OK) { |
653 | return TCL_ERROR; | return TCL_ERROR; |
654 | } | } |
655 | if (value < 0) { | if (value < 0) { |
656 | Tcl_AppendResult(interp, argv[i], | Tcl_AppendResult(interp, argv[i], |
657 | " is an invalid value: should NOT be < 0", | " is an invalid value: should NOT be < 0", |
658 | (char *) NULL); | (char *) NULL); |
659 | return TCL_ERROR; | return TCL_ERROR; |
660 | } | } |
661 | if (strncmp(argv[i], "-column", length) == 0) { | if (strncmp(argv[i], "-column", length) == 0) { |
662 | column = value; | column = value; |
663 | } else if (strncmp(argv[i], "-row", length) == 0) { | } else if (strncmp(argv[i], "-row", length) == 0) { |
664 | row = value; | row = value; |
665 | } else { | } else { |
666 | Tcl_AppendResult(interp, argv[i], | Tcl_AppendResult(interp, argv[i], |
667 | " is an invalid option: should be \"", | " is an invalid option: should be \"", |
668 | "-row, -column\"", | "-row, -column\"", |
669 | (char *) NULL); | (char *) NULL); |
670 | return TCL_ERROR; | return TCL_ERROR; |
671 | } | } |
672 | } | } |
673 | master = Tk_NameToWindow(interp, argv[2], tkwin); | master = Tk_NameToWindow(interp, argv[2], tkwin); |
674 | if (master == NULL) { | if (master == NULL) { |
675 | return TCL_ERROR; | return TCL_ERROR; |
676 | } | } |
677 | masterPtr = GetGrid(master); | masterPtr = GetGrid(master); |
678 | ||
679 | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; |
680 | slavePtr = slavePtr->nextPtr) { | slavePtr = slavePtr->nextPtr) { |
681 | if (column>=0 && (slavePtr->column > column | if (column>=0 && (slavePtr->column > column |
682 | || slavePtr->column+slavePtr->numCols-1 < column)) { | || slavePtr->column+slavePtr->numCols-1 < column)) { |
683 | continue; | continue; |
684 | } | } |
685 | if (row>=0 && (slavePtr->row > row || | if (row>=0 && (slavePtr->row > row || |
686 | slavePtr->row+slavePtr->numRows-1 < row)) { | slavePtr->row+slavePtr->numRows-1 < row)) { |
687 | continue; | continue; |
688 | } | } |
689 | Tcl_AppendElement(interp, Tk_PathName(slavePtr->tkwin)); | Tcl_AppendElement(interp, Tk_PathName(slavePtr->tkwin)); |
690 | } | } |
691 | ||
692 | /* | /* |
693 | * Sample argument combinations: | * Sample argument combinations: |
694 | * grid columnconfigure <master> <index> -option | * grid columnconfigure <master> <index> -option |
695 | * grid columnconfigure <master> <index> -option value -option value | * grid columnconfigure <master> <index> -option value -option value |
696 | * grid rowconfigure <master> <index> | * grid rowconfigure <master> <index> |
697 | * grid rowconfigure <master> <index> -option | * grid rowconfigure <master> <index> -option |
698 | * grid rowconfigure <master> <index> -option value -option value. | * grid rowconfigure <master> <index> -option value -option value. |
699 | */ | */ |
700 | ||
701 | } else if(((c == 'c') && (strncmp(argv[1], "columnconfigure", length) == 0) | } else if(((c == 'c') && (strncmp(argv[1], "columnconfigure", length) == 0) |
702 | && (length >= 3)) || | && (length >= 3)) || |
703 | ((c == 'r') && (strncmp(argv[1], "rowconfigure", length) == 0) | ((c == 'r') && (strncmp(argv[1], "rowconfigure", length) == 0) |
704 | && (length >=2))) { | && (length >=2))) { |
705 | Tk_Window master; | Tk_Window master; |
706 | SlotInfo *slotPtr = NULL; | SlotInfo *slotPtr = NULL; |
707 | int slot; /* the column or row number */ | int slot; /* the column or row number */ |
708 | size_t length; /* the # of chars in the "-option" string */ | size_t length; /* the # of chars in the "-option" string */ |
709 | int slotType; /* COLUMN or ROW */ | int slotType; /* COLUMN or ROW */ |
710 | int size; /* the configuration value */ | int size; /* the configuration value */ |
711 | int checkOnly; /* check the size only */ | int checkOnly; /* check the size only */ |
712 | int argcPtr; /* Number of items in index list */ | int argcPtr; /* Number of items in index list */ |
713 | char **argvPtr; /* array of indeces */ | char **argvPtr; /* array of indeces */ |
714 | char **indexP; /* String value of current index list item. */ | char **indexP; /* String value of current index list item. */ |
715 | int ok; /* temporary TCL result code */ | int ok; /* temporary TCL result code */ |
716 | int i; | int i; |
717 | ||
718 | if (((argc%2 != 0) && (argc>6)) || (argc < 4)) { | if (((argc%2 != 0) && (argc>6)) || (argc < 4)) { |
719 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
720 | " ", argv[1], " master index ?-option value...?\"", | " ", argv[1], " master index ?-option value...?\"", |
721 | (char *)NULL); | (char *)NULL); |
722 | return TCL_ERROR; | return TCL_ERROR; |
723 | } | } |
724 | ||
725 | master = Tk_NameToWindow(interp, argv[2], tkwin); | master = Tk_NameToWindow(interp, argv[2], tkwin); |
726 | if (master == NULL) { | if (master == NULL) { |
727 | return TCL_ERROR; | return TCL_ERROR; |
728 | } | } |
729 | ||
730 | if (Tcl_SplitList(interp, argv[3], &argcPtr, &argvPtr) != TCL_OK) { | if (Tcl_SplitList(interp, argv[3], &argcPtr, &argvPtr) != TCL_OK) { |
731 | return TCL_ERROR; | return TCL_ERROR; |
732 | } | } |
733 | ||
734 | checkOnly = ((argc == 4) || (argc == 5)); | checkOnly = ((argc == 4) || (argc == 5)); |
735 | masterPtr = GetGrid(master); | masterPtr = GetGrid(master); |
736 | slotType = (c == 'c') ? COLUMN : ROW; | slotType = (c == 'c') ? COLUMN : ROW; |
737 | if (checkOnly && argcPtr > 1) { | if (checkOnly && argcPtr > 1) { |
738 | Tcl_AppendResult(interp, argv[3], | Tcl_AppendResult(interp, argv[3], |
739 | " must be a single element.", (char *) NULL); | " must be a single element.", (char *) NULL); |
740 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
741 | return TCL_ERROR; | return TCL_ERROR; |
742 | } | } |
743 | for (indexP=argvPtr; *indexP != NULL; indexP++) { | for (indexP=argvPtr; *indexP != NULL; indexP++) { |
744 | if (Tcl_GetInt(interp, *indexP, &slot) != TCL_OK) { | if (Tcl_GetInt(interp, *indexP, &slot) != TCL_OK) { |
745 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
746 | return TCL_ERROR; | return TCL_ERROR; |
747 | } | } |
748 | ok = CheckSlotData(masterPtr, slot, slotType, checkOnly); | ok = CheckSlotData(masterPtr, slot, slotType, checkOnly); |
749 | if ((ok!=TCL_OK) && ((argc<4) || (argc>5))) { | if ((ok!=TCL_OK) && ((argc<4) || (argc>5))) { |
750 | Tcl_AppendResult(interp, argv[0], | Tcl_AppendResult(interp, argv[0], |
751 | " ", argv[1], ": \"", *argvPtr,"\" is out of range", | " ", argv[1], ": \"", *argvPtr,"\" is out of range", |
752 | (char *) NULL); | (char *) NULL); |
753 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
754 | return TCL_ERROR; | return TCL_ERROR; |
755 | } else if (ok == TCL_OK) { | } else if (ok == TCL_OK) { |
756 | slotPtr = (slotType == COLUMN) ? | slotPtr = (slotType == COLUMN) ? |
757 | masterPtr->masterDataPtr->columnPtr : | masterPtr->masterDataPtr->columnPtr : |
758 | masterPtr->masterDataPtr->rowPtr; | masterPtr->masterDataPtr->rowPtr; |
759 | } | } |
760 | ||
761 | /* | /* |
762 | * Return all of the options for this row or column. If the | * Return all of the options for this row or column. If the |
763 | * request is out of range, return all 0's. | * request is out of range, return all 0's. |
764 | */ | */ |
765 | ||
766 | if (argc == 4) { | if (argc == 4) { |
767 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
768 | } | } |
769 | if ((argc == 4) && (ok == TCL_OK)) { | if ((argc == 4) && (ok == TCL_OK)) { |
770 | char buf[64 + TCL_INTEGER_SPACE * 3]; | char buf[64 + TCL_INTEGER_SPACE * 3]; |
771 | ||
772 | sprintf(buf, "-minsize %d -pad %d -weight %d", | sprintf(buf, "-minsize %d -pad %d -weight %d", |
773 | slotPtr[slot].minSize,slotPtr[slot].pad, | slotPtr[slot].minSize,slotPtr[slot].pad, |
774 | slotPtr[slot].weight); | slotPtr[slot].weight); |
775 | Tcl_SetResult(interp, buf, TCL_VOLATILE); | Tcl_SetResult(interp, buf, TCL_VOLATILE); |
776 | return (TCL_OK); | return (TCL_OK); |
777 | } else if (argc == 4) { | } else if (argc == 4) { |
778 | Tcl_SetResult(interp, "-minsize 0 -pad 0 -weight 0", | Tcl_SetResult(interp, "-minsize 0 -pad 0 -weight 0", |
779 | TCL_STATIC); | TCL_STATIC); |
780 | return (TCL_OK); | return (TCL_OK); |
781 | } | } |
782 | ||
783 | /* | /* |
784 | * Loop through each option value pair, setting the values as required. | * Loop through each option value pair, setting the values as required. |
785 | * If only one option is given, with no value, the current value is | * If only one option is given, with no value, the current value is |
786 | * returned. | * returned. |
787 | */ | */ |
788 | ||
789 | for (i=4; i<argc; i+=2) { | for (i=4; i<argc; i+=2) { |
790 | length = strlen(argv[i]); | length = strlen(argv[i]); |
791 | if ((*argv[i] != '-') || length < 2) { | if ((*argv[i] != '-') || length < 2) { |
792 | Tcl_AppendResult(interp, "invalid arg \"", | Tcl_AppendResult(interp, "invalid arg \"", |
793 | argv[i], "\" :expecting -minsize, -pad, or -weight.", | argv[i], "\" :expecting -minsize, -pad, or -weight.", |
794 | (char *) NULL); | (char *) NULL); |
795 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
796 | return TCL_ERROR; | return TCL_ERROR; |
797 | } | } |
798 | if (strncmp(argv[i], "-minsize", length) == 0) { | if (strncmp(argv[i], "-minsize", length) == 0) { |
799 | if (argc == 5) { | if (argc == 5) { |
800 | char buf[TCL_INTEGER_SPACE]; | char buf[TCL_INTEGER_SPACE]; |
801 | int value; | int value; |
802 | ||
803 | value = (ok == TCL_OK) ? slotPtr[slot].minSize : 0; | value = (ok == TCL_OK) ? slotPtr[slot].minSize : 0; |
804 | sprintf(buf, "%d", value); | sprintf(buf, "%d", value); |
805 | Tcl_SetResult(interp, buf, TCL_VOLATILE); | Tcl_SetResult(interp, buf, TCL_VOLATILE); |
806 | } else if (Tk_GetPixels(interp, master, argv[i+1], &size) | } else if (Tk_GetPixels(interp, master, argv[i+1], &size) |
807 | != TCL_OK) { | != TCL_OK) { |
808 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
809 | return TCL_ERROR; | return TCL_ERROR; |
810 | } else { | } else { |
811 | slotPtr[slot].minSize = size; | slotPtr[slot].minSize = size; |
812 | } | } |
813 | } | } |
814 | else if (strncmp(argv[i], "-weight", length) == 0) { | else if (strncmp(argv[i], "-weight", length) == 0) { |
815 | int wt; | int wt; |
816 | if (argc == 5) { | if (argc == 5) { |
817 | char buf[TCL_INTEGER_SPACE]; | char buf[TCL_INTEGER_SPACE]; |
818 | int value; | int value; |
819 | ||
820 | value = (ok == TCL_OK) ? slotPtr[slot].weight : 0; | value = (ok == TCL_OK) ? slotPtr[slot].weight : 0; |
821 | sprintf(buf, "%d", value); | sprintf(buf, "%d", value); |
822 | Tcl_SetResult(interp, buf, TCL_VOLATILE); | Tcl_SetResult(interp, buf, TCL_VOLATILE); |
823 | } else if (Tcl_GetInt(interp, argv[i+1], &wt) != TCL_OK) { | } else if (Tcl_GetInt(interp, argv[i+1], &wt) != TCL_OK) { |
824 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
825 | return TCL_ERROR; | return TCL_ERROR; |
826 | } else if (wt < 0) { | } else if (wt < 0) { |
827 | Tcl_AppendResult(interp, "invalid arg \"", argv[i], | Tcl_AppendResult(interp, "invalid arg \"", argv[i], |
828 | "\": should be non-negative", (char *) NULL); | "\": should be non-negative", (char *) NULL); |
829 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
830 | return TCL_ERROR; | return TCL_ERROR; |
831 | } else { | } else { |
832 | slotPtr[slot].weight = wt; | slotPtr[slot].weight = wt; |
833 | } | } |
834 | } | } |
835 | else if (strncmp(argv[i], "-pad", length) == 0) { | else if (strncmp(argv[i], "-pad", length) == 0) { |
836 | if (argc == 5) { | if (argc == 5) { |
837 | char buf[TCL_INTEGER_SPACE]; | char buf[TCL_INTEGER_SPACE]; |
838 | int value; | int value; |
839 | ||
840 | value = (ok == TCL_OK) ? slotPtr[slot].pad : 0; | value = (ok == TCL_OK) ? slotPtr[slot].pad : 0; |
841 | sprintf(buf, "%d", value); | sprintf(buf, "%d", value); |
842 | Tcl_SetResult(interp, buf, TCL_VOLATILE); | Tcl_SetResult(interp, buf, TCL_VOLATILE); |
843 | } else if (Tk_GetPixels(interp, master, argv[i+1], &size) | } else if (Tk_GetPixels(interp, master, argv[i+1], &size) |
844 | != TCL_OK) { | != TCL_OK) { |
845 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
846 | return TCL_ERROR; | return TCL_ERROR; |
847 | } else if (size < 0) { | } else if (size < 0) { |
848 | Tcl_AppendResult(interp, "invalid arg \"", argv[i], | Tcl_AppendResult(interp, "invalid arg \"", argv[i], |
849 | "\": should be non-negative", (char *) NULL); | "\": should be non-negative", (char *) NULL); |
850 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
851 | return TCL_ERROR; | return TCL_ERROR; |
852 | } else { | } else { |
853 | slotPtr[slot].pad = size; | slotPtr[slot].pad = size; |
854 | } | } |
855 | } else { | } else { |
856 | Tcl_AppendResult(interp, "invalid arg \"", | Tcl_AppendResult(interp, "invalid arg \"", |
857 | argv[i], "\": expecting -minsize, -pad, or -weight.", | argv[i], "\": expecting -minsize, -pad, or -weight.", |
858 | (char *) NULL); | (char *) NULL); |
859 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
860 | return TCL_ERROR; | return TCL_ERROR; |
861 | } | } |
862 | } | } |
863 | } | } |
864 | Tcl_Free((char *)argvPtr); | Tcl_Free((char *)argvPtr); |
865 | ||
866 | /* | /* |
867 | * If we changed a property, re-arrange the table, | * If we changed a property, re-arrange the table, |
868 | * and check for constraint shrinkage. | * and check for constraint shrinkage. |
869 | */ | */ |
870 | ||
871 | if (argc != 5) { | if (argc != 5) { |
872 | if (slotType == ROW) { | if (slotType == ROW) { |
873 | int last = masterPtr->masterDataPtr->rowMax - 1; | int last = masterPtr->masterDataPtr->rowMax - 1; |
874 | while ((last >= 0) && (slotPtr[last].weight == 0) | while ((last >= 0) && (slotPtr[last].weight == 0) |
875 | && (slotPtr[last].pad == 0) | && (slotPtr[last].pad == 0) |
876 | && (slotPtr[last].minSize == 0)) { | && (slotPtr[last].minSize == 0)) { |
877 | last--; | last--; |
878 | } | } |
879 | masterPtr->masterDataPtr->rowMax = last+1; | masterPtr->masterDataPtr->rowMax = last+1; |
880 | } else { | } else { |
881 | int last = masterPtr->masterDataPtr->columnMax - 1; | int last = masterPtr->masterDataPtr->columnMax - 1; |
882 | while ((last >= 0) && (slotPtr[last].weight == 0) | while ((last >= 0) && (slotPtr[last].weight == 0) |
883 | && (slotPtr[last].pad == 0) | && (slotPtr[last].pad == 0) |
884 | && (slotPtr[last].minSize == 0)) { | && (slotPtr[last].minSize == 0)) { |
885 | last--; | last--; |
886 | } | } |
887 | masterPtr->masterDataPtr->columnMax = last + 1; | masterPtr->masterDataPtr->columnMax = last + 1; |
888 | } | } |
889 | ||
890 | if (masterPtr->abortPtr != NULL) { | if (masterPtr->abortPtr != NULL) { |
891 | *masterPtr->abortPtr = 1; | *masterPtr->abortPtr = 1; |
892 | } | } |
893 | if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { | if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { |
894 | masterPtr->flags |= REQUESTED_RELAYOUT; | masterPtr->flags |= REQUESTED_RELAYOUT; |
895 | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); |
896 | } | } |
897 | } | } |
898 | } else { | } else { |
899 | Tcl_AppendResult(interp, "bad option \"", argv[1], | Tcl_AppendResult(interp, "bad option \"", argv[1], |
900 | "\": must be bbox, columnconfigure, configure, forget, info, ", | "\": must be bbox, columnconfigure, configure, forget, info, ", |
901 | "location, propagate, remove, rowconfigure, size, or slaves.", | "location, propagate, remove, rowconfigure, size, or slaves.", |
902 | (char *) NULL); | (char *) NULL); |
903 | return TCL_ERROR; | return TCL_ERROR; |
904 | } | } |
905 | return TCL_OK; | return TCL_OK; |
906 | } | } |
907 | ||
908 | /* | /* |
909 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
910 | * | * |
911 | * GridReqProc -- | * GridReqProc -- |
912 | * | * |
913 | * This procedure is invoked by Tk_GeometryRequest for | * This procedure is invoked by Tk_GeometryRequest for |
914 | * windows managed by the grid. | * windows managed by the grid. |
915 | * | * |
916 | * Results: | * Results: |
917 | * None. | * None. |
918 | * | * |
919 | * Side effects: | * Side effects: |
920 | * Arranges for tkwin, and all its managed siblings, to | * Arranges for tkwin, and all its managed siblings, to |
921 | * be re-arranged at the next idle point. | * be re-arranged at the next idle point. |
922 | * | * |
923 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
924 | */ | */ |
925 | ||
926 | static void | static void |
927 | GridReqProc(clientData, tkwin) | GridReqProc(clientData, tkwin) |
928 | ClientData clientData; /* Grid's information about | ClientData clientData; /* Grid's information about |
929 | * window that got new preferred | * window that got new preferred |
930 | * geometry. */ | * geometry. */ |
931 | Tk_Window tkwin; /* Other Tk-related information | Tk_Window tkwin; /* Other Tk-related information |
932 | * about the window. */ | * about the window. */ |
933 | { | { |
934 | register Gridder *gridPtr = (Gridder *) clientData; | register Gridder *gridPtr = (Gridder *) clientData; |
935 | ||
936 | gridPtr = gridPtr->masterPtr; | gridPtr = gridPtr->masterPtr; |
937 | if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { | if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { |
938 | gridPtr->flags |= REQUESTED_RELAYOUT; | gridPtr->flags |= REQUESTED_RELAYOUT; |
939 | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); |
940 | } | } |
941 | } | } |
942 | ||
943 | /* | /* |
944 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
945 | * | * |
946 | * GridLostSlaveProc -- | * GridLostSlaveProc -- |
947 | * | * |
948 | * This procedure is invoked by Tk whenever some other geometry | * This procedure is invoked by Tk whenever some other geometry |
949 | * claims control over a slave that used to be managed by us. | * claims control over a slave that used to be managed by us. |
950 | * | * |
951 | * Results: | * Results: |
952 | * None. | * None. |
953 | * | * |
954 | * Side effects: | * Side effects: |
955 | * Forgets all grid-related information about the slave. | * Forgets all grid-related information about the slave. |
956 | * | * |
957 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
958 | */ | */ |
959 | ||
960 | static void | static void |
961 | GridLostSlaveProc(clientData, tkwin) | GridLostSlaveProc(clientData, tkwin) |
962 | ClientData clientData; /* Grid structure for slave window that | ClientData clientData; /* Grid structure for slave window that |
963 | * was stolen away. */ | * was stolen away. */ |
964 | Tk_Window tkwin; /* Tk's handle for the slave window. */ | Tk_Window tkwin; /* Tk's handle for the slave window. */ |
965 | { | { |
966 | register Gridder *slavePtr = (Gridder *) clientData; | register Gridder *slavePtr = (Gridder *) clientData; |
967 | ||
968 | if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { | if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { |
969 | Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); | Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); |
970 | } | } |
971 | Unlink(slavePtr); | Unlink(slavePtr); |
972 | Tk_UnmapWindow(slavePtr->tkwin); | Tk_UnmapWindow(slavePtr->tkwin); |
973 | } | } |
974 | ||
975 | /* | /* |
976 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
977 | * | * |
978 | * AdjustOffsets -- | * AdjustOffsets -- |
979 | * | * |
980 | * This procedure adjusts the size of the layout to fit in the | * This procedure adjusts the size of the layout to fit in the |
981 | * space provided. If it needs more space, the extra is added | * space provided. If it needs more space, the extra is added |
982 | * according to the weights. If it needs less, the space is removed | * according to the weights. If it needs less, the space is removed |
983 | * according to the weights, but at no time does the size drop below | * according to the weights, but at no time does the size drop below |
984 | * the minsize specified for that slot. | * the minsize specified for that slot. |
985 | * | * |
986 | * Results: | * Results: |
987 | * The initial offset of the layout, | * The initial offset of the layout, |
988 | * if all the weights are zero, else 0. | * if all the weights are zero, else 0. |
989 | * | * |
990 | * Side effects: | * Side effects: |
991 | * The slot offsets are modified to shrink the layout. | * The slot offsets are modified to shrink the layout. |
992 | * | * |
993 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
994 | */ | */ |
995 | ||
996 | static int | static int |
997 | AdjustOffsets(size, slots, slotPtr) | AdjustOffsets(size, slots, slotPtr) |
998 | int size; /* The total layout size (in pixels). */ | int size; /* The total layout size (in pixels). */ |
999 | int slots; /* Number of slots. */ | int slots; /* Number of slots. */ |
1000 | register SlotInfo *slotPtr; /* Pointer to slot array. */ | register SlotInfo *slotPtr; /* Pointer to slot array. */ |
1001 | { | { |
1002 | register int slot; /* Current slot. */ | register int slot; /* Current slot. */ |
1003 | int diff; /* Extra pixels needed to add to the layout. */ | int diff; /* Extra pixels needed to add to the layout. */ |
1004 | int totalWeight = 0; /* Sum of the weights for all the slots. */ | int totalWeight = 0; /* Sum of the weights for all the slots. */ |
1005 | int weight = 0; /* Sum of the weights so far. */ | int weight = 0; /* Sum of the weights so far. */ |
1006 | int minSize = 0; /* Minimum possible layout size. */ | int minSize = 0; /* Minimum possible layout size. */ |
1007 | int newDiff; /* The most pixels that can be added on | int newDiff; /* The most pixels that can be added on |
1008 | * the current pass. */ | * the current pass. */ |
1009 | ||
1010 | diff = size - slotPtr[slots-1].offset; | diff = size - slotPtr[slots-1].offset; |
1011 | ||
1012 | /* | /* |
1013 | * The layout is already the correct size; all done. | * The layout is already the correct size; all done. |
1014 | */ | */ |
1015 | ||
1016 | if (diff == 0) { | if (diff == 0) { |
1017 | return(0); | return(0); |
1018 | } | } |
1019 | ||
1020 | /* | /* |
1021 | * If all the weights are zero, center the layout in its parent if | * If all the weights are zero, center the layout in its parent if |
1022 | * there is extra space, else clip on the bottom/right. | * there is extra space, else clip on the bottom/right. |
1023 | */ | */ |
1024 | ||
1025 | for (slot=0; slot < slots; slot++) { | for (slot=0; slot < slots; slot++) { |
1026 | totalWeight += slotPtr[slot].weight; | totalWeight += slotPtr[slot].weight; |
1027 | } | } |
1028 | ||
1029 | if (totalWeight == 0 ) { | if (totalWeight == 0 ) { |
1030 | return(diff > 0 ? diff/2 : 0); | return(diff > 0 ? diff/2 : 0); |
1031 | } | } |
1032 | ||
1033 | /* | /* |
1034 | * Add extra space according to the slot weights. This is done | * Add extra space according to the slot weights. This is done |
1035 | * cumulatively to prevent round-off error accumulation. | * cumulatively to prevent round-off error accumulation. |
1036 | */ | */ |
1037 | ||
1038 | if (diff > 0) { | if (diff > 0) { |
1039 | for (weight=slot=0; slot < slots; slot++) { | for (weight=slot=0; slot < slots; slot++) { |
1040 | weight += slotPtr[slot].weight; | weight += slotPtr[slot].weight; |
1041 | slotPtr[slot].offset += diff * weight / totalWeight; | slotPtr[slot].offset += diff * weight / totalWeight; |
1042 | } | } |
1043 | return(0); | return(0); |
1044 | } | } |
1045 | ||
1046 | /* | /* |
1047 | * The layout must shrink below its requested size. Compute the | * The layout must shrink below its requested size. Compute the |
1048 | * minimum possible size by looking at the slot minSizes. | * minimum possible size by looking at the slot minSizes. |
1049 | */ | */ |
1050 | ||
1051 | for (slot=0; slot < slots; slot++) { | for (slot=0; slot < slots; slot++) { |
1052 | if (slotPtr[slot].weight > 0) { | if (slotPtr[slot].weight > 0) { |
1053 | minSize += slotPtr[slot].minSize; | minSize += slotPtr[slot].minSize; |
1054 | } else if (slot > 0) { | } else if (slot > 0) { |
1055 | minSize += slotPtr[slot].offset - slotPtr[slot-1].offset; | minSize += slotPtr[slot].offset - slotPtr[slot-1].offset; |
1056 | } else { | } else { |
1057 | minSize += slotPtr[slot].offset; | minSize += slotPtr[slot].offset; |
1058 | } | } |
1059 | } | } |
1060 | ||
1061 | /* | /* |
1062 | * If the requested size is less than the minimum required size, | * If the requested size is less than the minimum required size, |
1063 | * set the slot sizes to their minimum values, then clip on the | * set the slot sizes to their minimum values, then clip on the |
1064 | * bottom/right. | * bottom/right. |
1065 | */ | */ |
1066 | ||
1067 | if (size <= minSize) { | if (size <= minSize) { |
1068 | int offset = 0; | int offset = 0; |
1069 | for (slot=0; slot < slots; slot++) { | for (slot=0; slot < slots; slot++) { |
1070 | if (slotPtr[slot].weight > 0) { | if (slotPtr[slot].weight > 0) { |
1071 | offset += slotPtr[slot].minSize; | offset += slotPtr[slot].minSize; |
1072 | } else if (slot > 0) { | } else if (slot > 0) { |
1073 | offset += slotPtr[slot].offset - slotPtr[slot-1].offset; | offset += slotPtr[slot].offset - slotPtr[slot-1].offset; |
1074 | } else { | } else { |
1075 | offset += slotPtr[slot].offset; | offset += slotPtr[slot].offset; |
1076 | } | } |
1077 | slotPtr[slot].offset = offset; | slotPtr[slot].offset = offset; |
1078 | } | } |
1079 | return(0); | return(0); |
1080 | } | } |
1081 | ||
1082 | /* | /* |
1083 | * Remove space from slots according to their weights. The weights | * Remove space from slots according to their weights. The weights |
1084 | * get renormalized anytime a slot shrinks to its minimum size. | * get renormalized anytime a slot shrinks to its minimum size. |
1085 | */ | */ |
1086 | ||
1087 | while (diff < 0) { | while (diff < 0) { |
1088 | ||
1089 | /* | /* |
1090 | * Find the total weight for the shrinkable slots. | * Find the total weight for the shrinkable slots. |
1091 | */ | */ |
1092 | ||
1093 | for (totalWeight=slot=0; slot < slots; slot++) { | for (totalWeight=slot=0; slot < slots; slot++) { |
1094 | int current = (slot == 0) ? slotPtr[slot].offset : | int current = (slot == 0) ? slotPtr[slot].offset : |
1095 | slotPtr[slot].offset - slotPtr[slot-1].offset; | slotPtr[slot].offset - slotPtr[slot-1].offset; |
1096 | if (current > slotPtr[slot].minSize) { | if (current > slotPtr[slot].minSize) { |
1097 | totalWeight += slotPtr[slot].weight; | totalWeight += slotPtr[slot].weight; |
1098 | slotPtr[slot].temp = slotPtr[slot].weight; | slotPtr[slot].temp = slotPtr[slot].weight; |
1099 | } else { | } else { |
1100 | slotPtr[slot].temp = 0; | slotPtr[slot].temp = 0; |
1101 | } | } |
1102 | } | } |
1103 | if (totalWeight == 0) { | if (totalWeight == 0) { |
1104 | break; | break; |
1105 | } | } |
1106 | ||
1107 | /* | /* |
1108 | * Find the maximum amount of space we can distribute this pass. | * Find the maximum amount of space we can distribute this pass. |
1109 | */ | */ |
1110 | ||
1111 | newDiff = diff; | newDiff = diff; |
1112 | for (slot = 0; slot < slots; slot++) { | for (slot = 0; slot < slots; slot++) { |
1113 | int current; /* current size of this slot */ | int current; /* current size of this slot */ |
1114 | int maxDiff; /* max diff that would cause | int maxDiff; /* max diff that would cause |
1115 | * this slot to equal its minsize */ | * this slot to equal its minsize */ |
1116 | if (slotPtr[slot].temp == 0) { | if (slotPtr[slot].temp == 0) { |
1117 | continue; | continue; |
1118 | } | } |
1119 | current = (slot == 0) ? slotPtr[slot].offset : | current = (slot == 0) ? slotPtr[slot].offset : |
1120 | slotPtr[slot].offset - slotPtr[slot-1].offset; | slotPtr[slot].offset - slotPtr[slot-1].offset; |
1121 | maxDiff = totalWeight * (slotPtr[slot].minSize - current) | maxDiff = totalWeight * (slotPtr[slot].minSize - current) |
1122 | / slotPtr[slot].temp; | / slotPtr[slot].temp; |
1123 | if (maxDiff > newDiff) { | if (maxDiff > newDiff) { |
1124 | newDiff = maxDiff; | newDiff = maxDiff; |
1125 | } | } |
1126 | } | } |
1127 | ||
1128 | /* | /* |
1129 | * Now distribute the space. | * Now distribute the space. |
1130 | */ | */ |
1131 | ||
1132 | for (weight=slot=0; slot < slots; slot++) { | for (weight=slot=0; slot < slots; slot++) { |
1133 | weight += slotPtr[slot].temp; | weight += slotPtr[slot].temp; |
1134 | slotPtr[slot].offset += newDiff * weight / totalWeight; | slotPtr[slot].offset += newDiff * weight / totalWeight; |
1135 | } | } |
1136 | diff -= newDiff; | diff -= newDiff; |
1137 | } | } |
1138 | return(0); | return(0); |
1139 | } | } |
1140 | ||
1141 | /* | /* |
1142 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1143 | * | * |
1144 | * AdjustForSticky -- | * AdjustForSticky -- |
1145 | * | * |
1146 | * This procedure adjusts the size of a slave in its cavity based | * This procedure adjusts the size of a slave in its cavity based |
1147 | * on its "sticky" flags. | * on its "sticky" flags. |
1148 | * | * |
1149 | * Results: | * Results: |
1150 | * The input x, y, width, and height are changed to represent the | * The input x, y, width, and height are changed to represent the |
1151 | * desired coordinates of the slave. | * desired coordinates of the slave. |
1152 | * | * |
1153 | * Side effects: | * Side effects: |
1154 | * None. | * None. |
1155 | * | * |
1156 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1157 | */ | */ |
1158 | ||
1159 | static void | static void |
1160 | AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) | AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) |
1161 | Gridder *slavePtr; /* Slave window to arrange in its cavity. */ | Gridder *slavePtr; /* Slave window to arrange in its cavity. */ |
1162 | int *xPtr; /* Pixel location of the left edge of the cavity. */ | int *xPtr; /* Pixel location of the left edge of the cavity. */ |
1163 | int *yPtr; /* Pixel location of the top edge of the cavity. */ | int *yPtr; /* Pixel location of the top edge of the cavity. */ |
1164 | int *widthPtr; /* Width of the cavity (in pixels). */ | int *widthPtr; /* Width of the cavity (in pixels). */ |
1165 | int *heightPtr; /* Height of the cavity (in pixels). */ | int *heightPtr; /* Height of the cavity (in pixels). */ |
1166 | { | { |
1167 | int diffx=0; /* Cavity width - slave width. */ | int diffx=0; /* Cavity width - slave width. */ |
1168 | int diffy=0; /* Cavity hight - slave height. */ | int diffy=0; /* Cavity hight - slave height. */ |
1169 | int sticky = slavePtr->sticky; | int sticky = slavePtr->sticky; |
1170 | ||
1171 | *xPtr += slavePtr->padX/2; | *xPtr += slavePtr->padX/2; |
1172 | *widthPtr -= slavePtr->padX; | *widthPtr -= slavePtr->padX; |
1173 | *yPtr += slavePtr->padY/2; | *yPtr += slavePtr->padY/2; |
1174 | *heightPtr -= slavePtr->padY; | *heightPtr -= slavePtr->padY; |
1175 | ||
1176 | if (*widthPtr > (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX)) { | if (*widthPtr > (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX)) { |
1177 | diffx = *widthPtr - (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX); | diffx = *widthPtr - (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX); |
1178 | *widthPtr = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX; | *widthPtr = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX; |
1179 | } | } |
1180 | ||
1181 | if (*heightPtr > (Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY)) { | if (*heightPtr > (Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY)) { |
1182 | diffy = *heightPtr - (Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY); | diffy = *heightPtr - (Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY); |
1183 | *heightPtr = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY; | *heightPtr = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY; |
1184 | } | } |
1185 | ||
1186 | if (sticky&STICK_EAST && sticky&STICK_WEST) { | if (sticky&STICK_EAST && sticky&STICK_WEST) { |
1187 | *widthPtr += diffx; | *widthPtr += diffx; |
1188 | } | } |
1189 | if (sticky&STICK_NORTH && sticky&STICK_SOUTH) { | if (sticky&STICK_NORTH && sticky&STICK_SOUTH) { |
1190 | *heightPtr += diffy; | *heightPtr += diffy; |
1191 | } | } |
1192 | if (!(sticky&STICK_WEST)) { | if (!(sticky&STICK_WEST)) { |
1193 | *xPtr += (sticky&STICK_EAST) ? diffx : diffx/2; | *xPtr += (sticky&STICK_EAST) ? diffx : diffx/2; |
1194 | } | } |
1195 | if (!(sticky&STICK_NORTH)) { | if (!(sticky&STICK_NORTH)) { |
1196 | *yPtr += (sticky&STICK_SOUTH) ? diffy : diffy/2; | *yPtr += (sticky&STICK_SOUTH) ? diffy : diffy/2; |
1197 | } | } |
1198 | } | } |
1199 | ||
1200 | /* | /* |
1201 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1202 | * | * |
1203 | * ArrangeGrid -- | * ArrangeGrid -- |
1204 | * | * |
1205 | * This procedure is invoked (using the Tcl_DoWhenIdle | * This procedure is invoked (using the Tcl_DoWhenIdle |
1206 | * mechanism) to re-layout a set of windows managed by | * mechanism) to re-layout a set of windows managed by |
1207 | * the grid. It is invoked at idle time so that a | * the grid. It is invoked at idle time so that a |
1208 | * series of grid requests can be merged into a single | * series of grid requests can be merged into a single |
1209 | * layout operation. | * layout operation. |
1210 | * | * |
1211 | * Results: | * Results: |
1212 | * None. | * None. |
1213 | * | * |
1214 | * Side effects: | * Side effects: |
1215 | * The slaves of masterPtr may get resized or moved. | * The slaves of masterPtr may get resized or moved. |
1216 | * | * |
1217 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1218 | */ | */ |
1219 | ||
1220 | static void | static void |
1221 | ArrangeGrid(clientData) | ArrangeGrid(clientData) |
1222 | ClientData clientData; /* Structure describing parent whose slaves | ClientData clientData; /* Structure describing parent whose slaves |
1223 | * are to be re-layed out. */ | * are to be re-layed out. */ |
1224 | { | { |
1225 | register Gridder *masterPtr = (Gridder *) clientData; | register Gridder *masterPtr = (Gridder *) clientData; |
1226 | register Gridder *slavePtr; | register Gridder *slavePtr; |
1227 | GridMaster *slotPtr = masterPtr->masterDataPtr; | GridMaster *slotPtr = masterPtr->masterDataPtr; |
1228 | int abort; | int abort; |
1229 | int width, height; /* requested size of layout, in pixels */ | int width, height; /* requested size of layout, in pixels */ |
1230 | int realWidth, realHeight; /* actual size layout should take-up */ | int realWidth, realHeight; /* actual size layout should take-up */ |
1231 | ||
1232 | masterPtr->flags &= ~REQUESTED_RELAYOUT; | masterPtr->flags &= ~REQUESTED_RELAYOUT; |
1233 | ||
1234 | /* | /* |
1235 | * If the parent has no slaves anymore, then don't do anything | * If the parent has no slaves anymore, then don't do anything |
1236 | * at all: just leave the parent's size as-is. Otherwise there is | * at all: just leave the parent's size as-is. Otherwise there is |
1237 | * no way to "relinquish" control over the parent so another geometry | * no way to "relinquish" control over the parent so another geometry |
1238 | * manager can take over. | * manager can take over. |
1239 | */ | */ |
1240 | ||
1241 | if (masterPtr->slavePtr == NULL) { | if (masterPtr->slavePtr == NULL) { |
1242 | return; | return; |
1243 | } | } |
1244 | ||
1245 | if (masterPtr->masterDataPtr == NULL) { | if (masterPtr->masterDataPtr == NULL) { |
1246 | return; | return; |
1247 | } | } |
1248 | ||
1249 | /* | /* |
1250 | * Abort any nested call to ArrangeGrid for this window, since | * Abort any nested call to ArrangeGrid for this window, since |
1251 | * we'll do everything necessary here, and set up so this call | * we'll do everything necessary here, and set up so this call |
1252 | * can be aborted if necessary. | * can be aborted if necessary. |
1253 | */ | */ |
1254 | ||
1255 | if (masterPtr->abortPtr != NULL) { | if (masterPtr->abortPtr != NULL) { |
1256 | *masterPtr->abortPtr = 1; | *masterPtr->abortPtr = 1; |
1257 | } | } |
1258 | masterPtr->abortPtr = &abort; | masterPtr->abortPtr = &abort; |
1259 | abort = 0; | abort = 0; |
1260 | Tcl_Preserve((ClientData) masterPtr); | Tcl_Preserve((ClientData) masterPtr); |
1261 | ||
1262 | /* | /* |
1263 | * Call the constraint engine to fill in the row and column offsets. | * Call the constraint engine to fill in the row and column offsets. |
1264 | */ | */ |
1265 | ||
1266 | SetGridSize(masterPtr); | SetGridSize(masterPtr); |
1267 | width = ResolveConstraints(masterPtr, COLUMN, 0); | width = ResolveConstraints(masterPtr, COLUMN, 0); |
1268 | height = ResolveConstraints(masterPtr, ROW, 0); | height = ResolveConstraints(masterPtr, ROW, 0); |
1269 | width += 2*Tk_InternalBorderWidth(masterPtr->tkwin); | width += 2*Tk_InternalBorderWidth(masterPtr->tkwin); |
1270 | height += 2*Tk_InternalBorderWidth(masterPtr->tkwin); | height += 2*Tk_InternalBorderWidth(masterPtr->tkwin); |
1271 | ||
1272 | if (((width != Tk_ReqWidth(masterPtr->tkwin)) | if (((width != Tk_ReqWidth(masterPtr->tkwin)) |
1273 | || (height != Tk_ReqHeight(masterPtr->tkwin))) | || (height != Tk_ReqHeight(masterPtr->tkwin))) |
1274 | && !(masterPtr->flags & DONT_PROPAGATE)) { | && !(masterPtr->flags & DONT_PROPAGATE)) { |
1275 | Tk_GeometryRequest(masterPtr->tkwin, width, height); | Tk_GeometryRequest(masterPtr->tkwin, width, height); |
1276 | if (width>1 && height>1) { | if (width>1 && height>1) { |
1277 | masterPtr->flags |= REQUESTED_RELAYOUT; | masterPtr->flags |= REQUESTED_RELAYOUT; |
1278 | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); |
1279 | } | } |
1280 | masterPtr->abortPtr = NULL; | masterPtr->abortPtr = NULL; |
1281 | Tcl_Release((ClientData) masterPtr); | Tcl_Release((ClientData) masterPtr); |
1282 | return; | return; |
1283 | } | } |
1284 | ||
1285 | /* | /* |
1286 | * If the currently requested layout size doesn't match the parent's | * If the currently requested layout size doesn't match the parent's |
1287 | * window size, then adjust the slot offsets according to the | * window size, then adjust the slot offsets according to the |
1288 | * weights. If all of the weights are zero, center the layout in | * weights. If all of the weights are zero, center the layout in |
1289 | * its parent. I haven't decided what to do if the parent is smaller | * its parent. I haven't decided what to do if the parent is smaller |
1290 | * than the requested size. | * than the requested size. |
1291 | */ | */ |
1292 | ||
1293 | realWidth = Tk_Width(masterPtr->tkwin) - | realWidth = Tk_Width(masterPtr->tkwin) - |
1294 | 2*Tk_InternalBorderWidth(masterPtr->tkwin); | 2*Tk_InternalBorderWidth(masterPtr->tkwin); |
1295 | realHeight = Tk_Height(masterPtr->tkwin) - | realHeight = Tk_Height(masterPtr->tkwin) - |
1296 | 2*Tk_InternalBorderWidth(masterPtr->tkwin); | 2*Tk_InternalBorderWidth(masterPtr->tkwin); |
1297 | slotPtr->startX = AdjustOffsets(realWidth, | slotPtr->startX = AdjustOffsets(realWidth, |
1298 | MAX(slotPtr->columnEnd,slotPtr->columnMax), slotPtr->columnPtr); | MAX(slotPtr->columnEnd,slotPtr->columnMax), slotPtr->columnPtr); |
1299 | slotPtr->startY = AdjustOffsets(realHeight, | slotPtr->startY = AdjustOffsets(realHeight, |
1300 | MAX(slotPtr->rowEnd,slotPtr->rowMax), slotPtr->rowPtr); | MAX(slotPtr->rowEnd,slotPtr->rowMax), slotPtr->rowPtr); |
1301 | slotPtr->startX += Tk_InternalBorderWidth(masterPtr->tkwin); | slotPtr->startX += Tk_InternalBorderWidth(masterPtr->tkwin); |
1302 | slotPtr->startY += Tk_InternalBorderWidth(masterPtr->tkwin); | slotPtr->startY += Tk_InternalBorderWidth(masterPtr->tkwin); |
1303 | ||
1304 | /* | /* |
1305 | * Now adjust the actual size of the slave to its cavity by | * Now adjust the actual size of the slave to its cavity by |
1306 | * computing the cavity size, and adjusting the widget according | * computing the cavity size, and adjusting the widget according |
1307 | * to its stickyness. | * to its stickyness. |
1308 | */ | */ |
1309 | ||
1310 | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort; | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort; |
1311 | slavePtr = slavePtr->nextPtr) { | slavePtr = slavePtr->nextPtr) { |
1312 | int x, y; /* top left coordinate */ | int x, y; /* top left coordinate */ |
1313 | int width, height; /* slot or slave size */ | int width, height; /* slot or slave size */ |
1314 | int col = slavePtr->column; | int col = slavePtr->column; |
1315 | int row = slavePtr->row; | int row = slavePtr->row; |
1316 | ||
1317 | x = (col>0) ? slotPtr->columnPtr[col-1].offset : 0; | x = (col>0) ? slotPtr->columnPtr[col-1].offset : 0; |
1318 | y = (row>0) ? slotPtr->rowPtr[row-1].offset : 0; | y = (row>0) ? slotPtr->rowPtr[row-1].offset : 0; |
1319 | ||
1320 | width = slotPtr->columnPtr[slavePtr->numCols+col-1].offset - x; | width = slotPtr->columnPtr[slavePtr->numCols+col-1].offset - x; |
1321 | height = slotPtr->rowPtr[slavePtr->numRows+row-1].offset - y; | height = slotPtr->rowPtr[slavePtr->numRows+row-1].offset - y; |
1322 | ||
1323 | x += slotPtr->startX; | x += slotPtr->startX; |
1324 | y += slotPtr->startY; | y += slotPtr->startY; |
1325 | ||
1326 | AdjustForSticky(slavePtr, &x, &y, &width, &height); | AdjustForSticky(slavePtr, &x, &y, &width, &height); |
1327 | ||
1328 | /* | /* |
1329 | * Now put the window in the proper spot. (This was taken directly | * Now put the window in the proper spot. (This was taken directly |
1330 | * from tkPack.c.) If the slave is a child of the master, then | * from tkPack.c.) If the slave is a child of the master, then |
1331 | * do this here. Otherwise let Tk_MaintainGeometry do the work. | * do this here. Otherwise let Tk_MaintainGeometry do the work. |
1332 | */ | */ |
1333 | ||
1334 | if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { | if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { |
1335 | if ((width <= 0) || (height <= 0)) { | if ((width <= 0) || (height <= 0)) { |
1336 | Tk_UnmapWindow(slavePtr->tkwin); | Tk_UnmapWindow(slavePtr->tkwin); |
1337 | } else { | } else { |
1338 | if ((x != Tk_X(slavePtr->tkwin)) | if ((x != Tk_X(slavePtr->tkwin)) |
1339 | || (y != Tk_Y(slavePtr->tkwin)) | || (y != Tk_Y(slavePtr->tkwin)) |
1340 | || (width != Tk_Width(slavePtr->tkwin)) | || (width != Tk_Width(slavePtr->tkwin)) |
1341 | || (height != Tk_Height(slavePtr->tkwin))) { | || (height != Tk_Height(slavePtr->tkwin))) { |
1342 | Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); | Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); |
1343 | } | } |
1344 | if (abort) { | if (abort) { |
1345 | break; | break; |
1346 | } | } |
1347 | ||
1348 | /* | /* |
1349 | * Don't map the slave if the master isn't mapped: wait | * Don't map the slave if the master isn't mapped: wait |
1350 | * until the master gets mapped later. | * until the master gets mapped later. |
1351 | */ | */ |
1352 | ||
1353 | if (Tk_IsMapped(masterPtr->tkwin)) { | if (Tk_IsMapped(masterPtr->tkwin)) { |
1354 | Tk_MapWindow(slavePtr->tkwin); | Tk_MapWindow(slavePtr->tkwin); |
1355 | } | } |
1356 | } | } |
1357 | } else { | } else { |
1358 | if ((width <= 0) || (height <= 0)) { | if ((width <= 0) || (height <= 0)) { |
1359 | Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); | Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); |
1360 | Tk_UnmapWindow(slavePtr->tkwin); | Tk_UnmapWindow(slavePtr->tkwin); |
1361 | } else { | } else { |
1362 | Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, | Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, |
1363 | x, y, width, height); | x, y, width, height); |
1364 | } | } |
1365 | } | } |
1366 | } | } |
1367 | ||
1368 | masterPtr->abortPtr = NULL; | masterPtr->abortPtr = NULL; |
1369 | Tcl_Release((ClientData) masterPtr); | Tcl_Release((ClientData) masterPtr); |
1370 | } | } |
1371 | ||
1372 | /* | /* |
1373 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1374 | * | * |
1375 | * ResolveConstraints -- | * ResolveConstraints -- |
1376 | * | * |
1377 | * Resolve all of the column and row boundaries. Most of | * Resolve all of the column and row boundaries. Most of |
1378 | * the calculations are identical for rows and columns, so this procedure | * the calculations are identical for rows and columns, so this procedure |
1379 | * is called twice, once for rows, and again for columns. | * is called twice, once for rows, and again for columns. |
1380 | * | * |
1381 | * Results: | * Results: |
1382 | * The offset (in pixels) from the left/top edge of this layout is | * The offset (in pixels) from the left/top edge of this layout is |
1383 | * returned. | * returned. |
1384 | * | * |
1385 | * Side effects: | * Side effects: |
1386 | * The slot offsets are copied into the SlotInfo structure for the | * The slot offsets are copied into the SlotInfo structure for the |
1387 | * geometry master. | * geometry master. |
1388 | * | * |
1389 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1390 | */ | */ |
1391 | ||
1392 | static int | static int |
1393 | ResolveConstraints(masterPtr, slotType, maxOffset) | ResolveConstraints(masterPtr, slotType, maxOffset) |
1394 | Gridder *masterPtr; /* The geometry master for this grid. */ | Gridder *masterPtr; /* The geometry master for this grid. */ |
1395 | int slotType; /* Either ROW or COLUMN. */ | int slotType; /* Either ROW or COLUMN. */ |
1396 | int maxOffset; /* The actual maximum size of this layout | int maxOffset; /* The actual maximum size of this layout |
1397 | * in pixels, or 0 (not currently used). */ | * in pixels, or 0 (not currently used). */ |
1398 | { | { |
1399 | register SlotInfo *slotPtr; /* Pointer to row/col constraints. */ | register SlotInfo *slotPtr; /* Pointer to row/col constraints. */ |
1400 | register Gridder *slavePtr; /* List of slave windows in this grid. */ | register Gridder *slavePtr; /* List of slave windows in this grid. */ |
1401 | int constraintCount; /* Count of rows or columns that have | int constraintCount; /* Count of rows or columns that have |
1402 | * constraints. */ | * constraints. */ |
1403 | int slotCount; /* Last occupied row or column. */ | int slotCount; /* Last occupied row or column. */ |
1404 | int gridCount; /* The larger of slotCount and constraintCount. | int gridCount; /* The larger of slotCount and constraintCount. |
1405 | */ | */ |
1406 | GridLayout *layoutPtr; /* Temporary layout structure. */ | GridLayout *layoutPtr; /* Temporary layout structure. */ |
1407 | int requiredSize; /* The natural size of the grid (pixels). | int requiredSize; /* The natural size of the grid (pixels). |
1408 | * This is the minimum size needed to | * This is the minimum size needed to |
1409 | * accomodate all of the slaves at their | * accomodate all of the slaves at their |
1410 | * requested sizes. */ | * requested sizes. */ |
1411 | int offset; /* The pixel offset of the right edge of the | int offset; /* The pixel offset of the right edge of the |
1412 | * current slot from the beginning of the | * current slot from the beginning of the |
1413 | * layout. */ | * layout. */ |
1414 | int slot; /* The current slot. */ | int slot; /* The current slot. */ |
1415 | int start; /* The first slot of a contiguous set whose | int start; /* The first slot of a contiguous set whose |
1416 | * constraints are not yet fully resolved. */ | * constraints are not yet fully resolved. */ |
1417 | int end; /* The Last slot of a contiguous set whose | int end; /* The Last slot of a contiguous set whose |
1418 | * constraints are not yet fully resolved. */ | * constraints are not yet fully resolved. */ |
1419 | ||
1420 | /* | /* |
1421 | * For typical sized tables, we'll use stack space for the layout data | * For typical sized tables, we'll use stack space for the layout data |
1422 | * to avoid the overhead of a malloc and free for every layout. | * to avoid the overhead of a malloc and free for every layout. |
1423 | */ | */ |
1424 | ||
1425 | GridLayout layoutData[TYPICAL_SIZE + 1]; | GridLayout layoutData[TYPICAL_SIZE + 1]; |
1426 | ||
1427 | if (slotType == COLUMN) { | if (slotType == COLUMN) { |
1428 | constraintCount = masterPtr->masterDataPtr->columnMax; | constraintCount = masterPtr->masterDataPtr->columnMax; |
1429 | slotCount = masterPtr->masterDataPtr->columnEnd; | slotCount = masterPtr->masterDataPtr->columnEnd; |
1430 | slotPtr = masterPtr->masterDataPtr->columnPtr; | slotPtr = masterPtr->masterDataPtr->columnPtr; |
1431 | } else { | } else { |
1432 | constraintCount = masterPtr->masterDataPtr->rowMax; | constraintCount = masterPtr->masterDataPtr->rowMax; |
1433 | slotCount = masterPtr->masterDataPtr->rowEnd; | slotCount = masterPtr->masterDataPtr->rowEnd; |
1434 | slotPtr = masterPtr->masterDataPtr->rowPtr; | slotPtr = masterPtr->masterDataPtr->rowPtr; |
1435 | } | } |
1436 | ||
1437 | /* | /* |
1438 | * Make sure there is enough memory for the layout. | * Make sure there is enough memory for the layout. |
1439 | */ | */ |
1440 | ||
1441 | gridCount = MAX(constraintCount,slotCount); | gridCount = MAX(constraintCount,slotCount); |
1442 | if (gridCount >= TYPICAL_SIZE) { | if (gridCount >= TYPICAL_SIZE) { |
1443 | layoutPtr = (GridLayout *) ckalloc(sizeof(GridLayout) * (1+gridCount)); | layoutPtr = (GridLayout *) ckalloc(sizeof(GridLayout) * (1+gridCount)); |
1444 | } else { | } else { |
1445 | layoutPtr = layoutData; | layoutPtr = layoutData; |
1446 | } | } |
1447 | ||
1448 | /* | /* |
1449 | * Allocate an extra layout slot to represent the left/top edge of | * Allocate an extra layout slot to represent the left/top edge of |
1450 | * the 0th slot to make it easier to calculate slot widths from | * the 0th slot to make it easier to calculate slot widths from |
1451 | * offsets without special case code. | * offsets without special case code. |
1452 | * Initialize the "dummy" slot to the left/top of the table. | * Initialize the "dummy" slot to the left/top of the table. |
1453 | * This slot avoids special casing the first slot. | * This slot avoids special casing the first slot. |
1454 | */ | */ |
1455 | ||
1456 | layoutPtr->minOffset = 0; | layoutPtr->minOffset = 0; |
1457 | layoutPtr->maxOffset = 0; | layoutPtr->maxOffset = 0; |
1458 | layoutPtr++; | layoutPtr++; |
1459 | ||
1460 | /* | /* |
1461 | * Step 1. | * Step 1. |
1462 | * Copy the slot constraints into the layout structure, | * Copy the slot constraints into the layout structure, |
1463 | * and initialize the rest of the fields. | * and initialize the rest of the fields. |
1464 | */ | */ |
1465 | ||
1466 | for (slot=0; slot < constraintCount; slot++) { | for (slot=0; slot < constraintCount; slot++) { |
1467 | layoutPtr[slot].minSize = slotPtr[slot].minSize; | layoutPtr[slot].minSize = slotPtr[slot].minSize; |
1468 | layoutPtr[slot].weight = slotPtr[slot].weight; | layoutPtr[slot].weight = slotPtr[slot].weight; |
1469 | layoutPtr[slot].pad = slotPtr[slot].pad; | layoutPtr[slot].pad = slotPtr[slot].pad; |
1470 | layoutPtr[slot].binNextPtr = NULL; | layoutPtr[slot].binNextPtr = NULL; |
1471 | } | } |
1472 | for(;slot<gridCount;slot++) { | for(;slot<gridCount;slot++) { |
1473 | layoutPtr[slot].minSize = 0; | layoutPtr[slot].minSize = 0; |
1474 | layoutPtr[slot].weight = 0; | layoutPtr[slot].weight = 0; |
1475 | layoutPtr[slot].pad = 0; | layoutPtr[slot].pad = 0; |
1476 | layoutPtr[slot].binNextPtr = NULL; | layoutPtr[slot].binNextPtr = NULL; |
1477 | } | } |
1478 | ||
1479 | /* | /* |
1480 | * Step 2. | * Step 2. |
1481 | * Slaves with a span of 1 are used to determine the minimum size of | * Slaves with a span of 1 are used to determine the minimum size of |
1482 | * each slot. Slaves whose span is two or more slots don't | * each slot. Slaves whose span is two or more slots don't |
1483 | * contribute to the minimum size of each slot directly, but can cause | * contribute to the minimum size of each slot directly, but can cause |
1484 | * slots to grow if their size exceeds the the sizes of the slots they | * slots to grow if their size exceeds the the sizes of the slots they |
1485 | * span. | * span. |
1486 | * | * |
1487 | * Bin all slaves whose spans are > 1 by their right edges. This | * Bin all slaves whose spans are > 1 by their right edges. This |
1488 | * allows the computation on minimum and maximum possible layout | * allows the computation on minimum and maximum possible layout |
1489 | * sizes at each slot boundary, without the need to re-sort the slaves. | * sizes at each slot boundary, without the need to re-sort the slaves. |
1490 | */ | */ |
1491 | ||
1492 | switch (slotType) { | switch (slotType) { |
1493 | case COLUMN: | case COLUMN: |
1494 | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; |
1495 | slavePtr = slavePtr->nextPtr) { | slavePtr = slavePtr->nextPtr) { |
1496 | int rightEdge = slavePtr->column + slavePtr->numCols - 1; | int rightEdge = slavePtr->column + slavePtr->numCols - 1; |
1497 | slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + | slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + |
1498 | slavePtr->padX + slavePtr->iPadX + slavePtr->doubleBw; | slavePtr->padX + slavePtr->iPadX + slavePtr->doubleBw; |
1499 | if (slavePtr->numCols > 1) { | if (slavePtr->numCols > 1) { |
1500 | slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; | slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; |
1501 | layoutPtr[rightEdge].binNextPtr = slavePtr; | layoutPtr[rightEdge].binNextPtr = slavePtr; |
1502 | } else { | } else { |
1503 | int size = slavePtr->size + layoutPtr[rightEdge].pad; | int size = slavePtr->size + layoutPtr[rightEdge].pad; |
1504 | if (size > layoutPtr[rightEdge].minSize) { | if (size > layoutPtr[rightEdge].minSize) { |
1505 | layoutPtr[rightEdge].minSize = size; | layoutPtr[rightEdge].minSize = size; |
1506 | } | } |
1507 | } | } |
1508 | } | } |
1509 | break; | break; |
1510 | case ROW: | case ROW: |
1511 | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; |
1512 | slavePtr = slavePtr->nextPtr) { | slavePtr = slavePtr->nextPtr) { |
1513 | int rightEdge = slavePtr->row + slavePtr->numRows - 1; | int rightEdge = slavePtr->row + slavePtr->numRows - 1; |
1514 | slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + | slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + |
1515 | slavePtr->padY + slavePtr->iPadY + slavePtr->doubleBw; | slavePtr->padY + slavePtr->iPadY + slavePtr->doubleBw; |
1516 | if (slavePtr->numRows > 1) { | if (slavePtr->numRows > 1) { |
1517 | slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; | slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; |
1518 | layoutPtr[rightEdge].binNextPtr = slavePtr; | layoutPtr[rightEdge].binNextPtr = slavePtr; |
1519 | } else { | } else { |
1520 | int size = slavePtr->size + layoutPtr[rightEdge].pad; | int size = slavePtr->size + layoutPtr[rightEdge].pad; |
1521 | if (size > layoutPtr[rightEdge].minSize) { | if (size > layoutPtr[rightEdge].minSize) { |
1522 | layoutPtr[rightEdge].minSize = size; | layoutPtr[rightEdge].minSize = size; |
1523 | } | } |
1524 | } | } |
1525 | } | } |
1526 | break; | break; |
1527 | } | } |
1528 | ||
1529 | /* | /* |
1530 | * Step 3. | * Step 3. |
1531 | * Determine the minimum slot offsets going from left to right | * Determine the minimum slot offsets going from left to right |
1532 | * that would fit all of the slaves. This determines the minimum | * that would fit all of the slaves. This determines the minimum |
1533 | */ | */ |
1534 | ||
1535 | for (offset=slot=0; slot < gridCount; slot++) { | for (offset=slot=0; slot < gridCount; slot++) { |
1536 | layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset; | layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset; |
1537 | for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; | for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; |
1538 | slavePtr = slavePtr->binNextPtr) { | slavePtr = slavePtr->binNextPtr) { |
1539 | int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; | int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; |
1540 | int required = slavePtr->size + layoutPtr[slot - span].minOffset; | int required = slavePtr->size + layoutPtr[slot - span].minOffset; |
1541 | if (required > layoutPtr[slot].minOffset) { | if (required > layoutPtr[slot].minOffset) { |
1542 | layoutPtr[slot].minOffset = required; | layoutPtr[slot].minOffset = required; |
1543 | } | } |
1544 | } | } |
1545 | offset = layoutPtr[slot].minOffset; | offset = layoutPtr[slot].minOffset; |
1546 | } | } |
1547 | ||
1548 | /* | /* |
1549 | * At this point, we know the minimum required size of the entire layout. | * At this point, we know the minimum required size of the entire layout. |
1550 | * It might be prudent to stop here if our "master" will resize itself | * It might be prudent to stop here if our "master" will resize itself |
1551 | * to this size. | * to this size. |
1552 | */ | */ |
1553 | ||
1554 | requiredSize = offset; | requiredSize = offset; |
1555 | if (maxOffset > offset) { | if (maxOffset > offset) { |
1556 | offset=maxOffset; | offset=maxOffset; |
1557 | } | } |
1558 | ||
1559 | /* | /* |
1560 | * Step 4. | * Step 4. |
1561 | * Determine the minimum slot offsets going from right to left, | * Determine the minimum slot offsets going from right to left, |
1562 | * bounding the pixel range of each slot boundary. | * bounding the pixel range of each slot boundary. |
1563 | * Pre-fill all of the right offsets with the actual size of the table; | * Pre-fill all of the right offsets with the actual size of the table; |
1564 | * they will be reduced as required. | * they will be reduced as required. |
1565 | */ | */ |
1566 | ||
1567 | for (slot=0; slot < gridCount; slot++) { | for (slot=0; slot < gridCount; slot++) { |
1568 | layoutPtr[slot].maxOffset = offset; | layoutPtr[slot].maxOffset = offset; |
1569 | } | } |
1570 | for (slot=gridCount-1; slot > 0;) { | for (slot=gridCount-1; slot > 0;) { |
1571 | for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; | for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; |
1572 | slavePtr = slavePtr->binNextPtr) { | slavePtr = slavePtr->binNextPtr) { |
1573 | int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; | int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; |
1574 | int require = offset - slavePtr->size; | int require = offset - slavePtr->size; |
1575 | int startSlot = slot - span; | int startSlot = slot - span; |
1576 | if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) { | if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) { |
1577 | layoutPtr[startSlot].maxOffset = require; | layoutPtr[startSlot].maxOffset = require; |
1578 | } | } |
1579 | } | } |
1580 | offset -= layoutPtr[slot].minSize; | offset -= layoutPtr[slot].minSize; |
1581 | slot--; | slot--; |
1582 | if (layoutPtr[slot].maxOffset < offset) { | if (layoutPtr[slot].maxOffset < offset) { |
1583 | offset = layoutPtr[slot].maxOffset; | offset = layoutPtr[slot].maxOffset; |
1584 | } else { | } else { |
1585 | layoutPtr[slot].maxOffset = offset; | layoutPtr[slot].maxOffset = offset; |
1586 | } | } |
1587 | } | } |
1588 | ||
1589 | /* | /* |
1590 | * Step 5. | * Step 5. |
1591 | * At this point, each slot boundary has a range of values that | * At this point, each slot boundary has a range of values that |
1592 | * will satisfy the overall layout size. | * will satisfy the overall layout size. |
1593 | * Make repeated passes over the layout structure looking for | * Make repeated passes over the layout structure looking for |
1594 | * spans of slot boundaries where the minOffsets are less than | * spans of slot boundaries where the minOffsets are less than |
1595 | * the maxOffsets, and adjust the offsets according to the slot | * the maxOffsets, and adjust the offsets according to the slot |
1596 | * weights. At each pass, at least one slot boundary will have | * weights. At each pass, at least one slot boundary will have |
1597 | * its range of possible values fixed at a single value. | * its range of possible values fixed at a single value. |
1598 | */ | */ |
1599 | ||
1600 | for (start=0; start < gridCount;) { | for (start=0; start < gridCount;) { |
1601 | int totalWeight = 0; /* Sum of the weights for all of the | int totalWeight = 0; /* Sum of the weights for all of the |
1602 | * slots in this span. */ | * slots in this span. */ |
1603 | int need = 0; /* The minimum space needed to layout | int need = 0; /* The minimum space needed to layout |
1604 | * this span. */ | * this span. */ |
1605 | int have; /* The actual amount of space that will | int have; /* The actual amount of space that will |
1606 | * be taken up by this span. */ | * be taken up by this span. */ |
1607 | int weight; /* Cumulative weights of the columns in | int weight; /* Cumulative weights of the columns in |
1608 | * this span. */ | * this span. */ |
1609 | int noWeights = 0; /* True if the span has no weights. */ | int noWeights = 0; /* True if the span has no weights. */ |
1610 | ||
1611 | /* | /* |
1612 | * Find a span by identifying ranges of slots whose edges are | * Find a span by identifying ranges of slots whose edges are |
1613 | * already constrained at fixed offsets, but whose internal | * already constrained at fixed offsets, but whose internal |
1614 | * slot boundaries have a range of possible positions. | * slot boundaries have a range of possible positions. |
1615 | */ | */ |
1616 | ||
1617 | if (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) { | if (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) { |
1618 | start++; | start++; |
1619 | continue; | continue; |
1620 | } | } |
1621 | ||
1622 | for (end=start+1; end<gridCount; end++) { | for (end=start+1; end<gridCount; end++) { |
1623 | if (layoutPtr[end].minOffset == layoutPtr[end].maxOffset) { | if (layoutPtr[end].minOffset == layoutPtr[end].maxOffset) { |
1624 | break; | break; |
1625 | } | } |
1626 | } | } |
1627 | ||
1628 | /* | /* |
1629 | * We found a span. Compute the total weight, minumum space required, | * We found a span. Compute the total weight, minumum space required, |
1630 | * for this span, and the actual amount of space the span should | * for this span, and the actual amount of space the span should |
1631 | * use. | * use. |
1632 | */ | */ |
1633 | ||
1634 | for (slot=start; slot<=end; slot++) { | for (slot=start; slot<=end; slot++) { |
1635 | totalWeight += layoutPtr[slot].weight; | totalWeight += layoutPtr[slot].weight; |
1636 | need += layoutPtr[slot].minSize; | need += layoutPtr[slot].minSize; |
1637 | } | } |
1638 | have = layoutPtr[end].maxOffset - layoutPtr[start-1].minOffset; | have = layoutPtr[end].maxOffset - layoutPtr[start-1].minOffset; |
1639 | ||
1640 | /* | /* |
1641 | * If all the weights in the span are zero, then distribute the | * If all the weights in the span are zero, then distribute the |
1642 | * extra space evenly. | * extra space evenly. |
1643 | */ | */ |
1644 | ||
1645 | if (totalWeight == 0) { | if (totalWeight == 0) { |
1646 | noWeights++; | noWeights++; |
1647 | totalWeight = end - start + 1; | totalWeight = end - start + 1; |
1648 | } | } |
1649 | ||
1650 | /* | /* |
1651 | * It might not be possible to give the span all of the space | * It might not be possible to give the span all of the space |
1652 | * available on this pass without violating the size constraints | * available on this pass without violating the size constraints |
1653 | * of one or more of the internal slot boundaries. | * of one or more of the internal slot boundaries. |
1654 | * Determine the maximum amount of space that when added to the | * Determine the maximum amount of space that when added to the |
1655 | * entire span, would cause a slot boundary to have its possible | * entire span, would cause a slot boundary to have its possible |
1656 | * range reduced to one value, and reduce the amount of extra | * range reduced to one value, and reduce the amount of extra |
1657 | * space allocated on this pass accordingly. | * space allocated on this pass accordingly. |
1658 | * | * |
1659 | * The calculation is done cumulatively to avoid accumulating | * The calculation is done cumulatively to avoid accumulating |
1660 | * roundoff errors. | * roundoff errors. |
1661 | */ | */ |
1662 | ||
1663 | for (weight=0,slot=start; slot<end; slot++) { | for (weight=0,slot=start; slot<end; slot++) { |
1664 | int diff = layoutPtr[slot].maxOffset - layoutPtr[slot].minOffset; | int diff = layoutPtr[slot].maxOffset - layoutPtr[slot].minOffset; |
1665 | weight += noWeights ? 1 : layoutPtr[slot].weight; | weight += noWeights ? 1 : layoutPtr[slot].weight; |
1666 | if ((noWeights || layoutPtr[slot].weight>0) && | if ((noWeights || layoutPtr[slot].weight>0) && |
1667 | (diff*totalWeight/weight) < (have-need)) { | (diff*totalWeight/weight) < (have-need)) { |
1668 | have = diff * totalWeight / weight + need; | have = diff * totalWeight / weight + need; |
1669 | } | } |
1670 | } | } |
1671 | ||
1672 | /* | /* |
1673 | * Now distribute the extra space among the slots by | * Now distribute the extra space among the slots by |
1674 | * adjusting the minSizes and minOffsets. | * adjusting the minSizes and minOffsets. |
1675 | */ | */ |
1676 | ||
1677 | for (weight=0,slot=start; slot<end; slot++) { | for (weight=0,slot=start; slot<end; slot++) { |
1678 | weight += noWeights ? 1 : layoutPtr[slot].weight; | weight += noWeights ? 1 : layoutPtr[slot].weight; |
1679 | layoutPtr[slot].minOffset += | layoutPtr[slot].minOffset += |
1680 | (int)((double) (have-need) * weight/totalWeight + 0.5); | (int)((double) (have-need) * weight/totalWeight + 0.5); |
1681 | layoutPtr[slot].minSize = layoutPtr[slot].minOffset | layoutPtr[slot].minSize = layoutPtr[slot].minOffset |
1682 | - layoutPtr[slot-1].minOffset; | - layoutPtr[slot-1].minOffset; |
1683 | } | } |
1684 | layoutPtr[slot].minSize = layoutPtr[slot].minOffset | layoutPtr[slot].minSize = layoutPtr[slot].minOffset |
1685 | - layoutPtr[slot-1].minOffset; | - layoutPtr[slot-1].minOffset; |
1686 | ||
1687 | /* | /* |
1688 | * Having pushed the top/left boundaries of the slots to | * Having pushed the top/left boundaries of the slots to |
1689 | * take up extra space, the bottom/right space is recalculated | * take up extra space, the bottom/right space is recalculated |
1690 | * to propagate the new space allocation. | * to propagate the new space allocation. |
1691 | */ | */ |
1692 | ||
1693 | for (slot=end; slot > start; slot--) { | for (slot=end; slot > start; slot--) { |
1694 | layoutPtr[slot-1].maxOffset = | layoutPtr[slot-1].maxOffset = |
1695 | layoutPtr[slot].maxOffset-layoutPtr[slot].minSize; | layoutPtr[slot].maxOffset-layoutPtr[slot].minSize; |
1696 | } | } |
1697 | } | } |
1698 | ||
1699 | ||
1700 | /* | /* |
1701 | * Step 6. | * Step 6. |
1702 | * All of the space has been apportioned; copy the | * All of the space has been apportioned; copy the |
1703 | * layout information back into the master. | * layout information back into the master. |
1704 | */ | */ |
1705 | ||
1706 | for (slot=0; slot < gridCount; slot++) { | for (slot=0; slot < gridCount; slot++) { |
1707 | slotPtr[slot].offset = layoutPtr[slot].minOffset; | slotPtr[slot].offset = layoutPtr[slot].minOffset; |
1708 | } | } |
1709 | ||
1710 | --layoutPtr; | --layoutPtr; |
1711 | if (layoutPtr != layoutData) { | if (layoutPtr != layoutData) { |
1712 | Tcl_Free((char *)layoutPtr); | Tcl_Free((char *)layoutPtr); |
1713 | } | } |
1714 | return requiredSize; | return requiredSize; |
1715 | } | } |
1716 | ||
1717 | /* | /* |
1718 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1719 | * | * |
1720 | * GetGrid -- | * GetGrid -- |
1721 | * | * |
1722 | * This internal procedure is used to locate a Grid | * This internal procedure is used to locate a Grid |
1723 | * structure for a given window, creating one if one | * structure for a given window, creating one if one |
1724 | * doesn't exist already. | * doesn't exist already. |
1725 | * | * |
1726 | * Results: | * Results: |
1727 | * The return value is a pointer to the Grid structure | * The return value is a pointer to the Grid structure |
1728 | * corresponding to tkwin. | * corresponding to tkwin. |
1729 | * | * |
1730 | * Side effects: | * Side effects: |
1731 | * A new grid structure may be created. If so, then | * A new grid structure may be created. If so, then |
1732 | * a callback is set up to clean things up when the | * a callback is set up to clean things up when the |
1733 | * window is deleted. | * window is deleted. |
1734 | * | * |
1735 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1736 | */ | */ |
1737 | ||
1738 | static Gridder * | static Gridder * |
1739 | GetGrid(tkwin) | GetGrid(tkwin) |
1740 | Tk_Window tkwin; /* Token for window for which | Tk_Window tkwin; /* Token for window for which |
1741 | * grid structure is desired. */ | * grid structure is desired. */ |
1742 | { | { |
1743 | register Gridder *gridPtr; | register Gridder *gridPtr; |
1744 | Tcl_HashEntry *hPtr; | Tcl_HashEntry *hPtr; |
1745 | int new; | int new; |
1746 | TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; | TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; |
1747 | ||
1748 | if (!dispPtr->gridInit) { | if (!dispPtr->gridInit) { |
1749 | Tcl_InitHashTable(&dispPtr->gridHashTable, TCL_ONE_WORD_KEYS); | Tcl_InitHashTable(&dispPtr->gridHashTable, TCL_ONE_WORD_KEYS); |
1750 | dispPtr->gridInit = 1; | dispPtr->gridInit = 1; |
1751 | } | } |
1752 | ||
1753 | /* | /* |
1754 | * See if there's already grid for this window. If not, | * See if there's already grid for this window. If not, |
1755 | * then create a new one. | * then create a new one. |
1756 | */ | */ |
1757 | ||
1758 | hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char *) tkwin, &new); | hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char *) tkwin, &new); |
1759 | if (!new) { | if (!new) { |
1760 | return (Gridder *) Tcl_GetHashValue(hPtr); | return (Gridder *) Tcl_GetHashValue(hPtr); |
1761 | } | } |
1762 | gridPtr = (Gridder *) ckalloc(sizeof(Gridder)); | gridPtr = (Gridder *) ckalloc(sizeof(Gridder)); |
1763 | gridPtr->tkwin = tkwin; | gridPtr->tkwin = tkwin; |
1764 | gridPtr->masterPtr = NULL; | gridPtr->masterPtr = NULL; |
1765 | gridPtr->masterDataPtr = NULL; | gridPtr->masterDataPtr = NULL; |
1766 | gridPtr->nextPtr = NULL; | gridPtr->nextPtr = NULL; |
1767 | gridPtr->slavePtr = NULL; | gridPtr->slavePtr = NULL; |
1768 | gridPtr->binNextPtr = NULL; | gridPtr->binNextPtr = NULL; |
1769 | ||
1770 | gridPtr->column = gridPtr->row = -1; | gridPtr->column = gridPtr->row = -1; |
1771 | gridPtr->numCols = 1; | gridPtr->numCols = 1; |
1772 | gridPtr->numRows = 1; | gridPtr->numRows = 1; |
1773 | ||
1774 | gridPtr->padX = gridPtr->padY = 0; | gridPtr->padX = gridPtr->padY = 0; |
1775 | gridPtr->iPadX = gridPtr->iPadY = 0; | gridPtr->iPadX = gridPtr->iPadY = 0; |
1776 | gridPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; | gridPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; |
1777 | gridPtr->abortPtr = NULL; | gridPtr->abortPtr = NULL; |
1778 | gridPtr->flags = 0; | gridPtr->flags = 0; |
1779 | gridPtr->sticky = 0; | gridPtr->sticky = 0; |
1780 | gridPtr->size = 0; | gridPtr->size = 0; |
1781 | gridPtr->masterDataPtr = NULL; | gridPtr->masterDataPtr = NULL; |
1782 | Tcl_SetHashValue(hPtr, gridPtr); | Tcl_SetHashValue(hPtr, gridPtr); |
1783 | Tk_CreateEventHandler(tkwin, StructureNotifyMask, | Tk_CreateEventHandler(tkwin, StructureNotifyMask, |
1784 | GridStructureProc, (ClientData) gridPtr); | GridStructureProc, (ClientData) gridPtr); |
1785 | return gridPtr; | return gridPtr; |
1786 | } | } |
1787 | ||
1788 | /* | /* |
1789 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1790 | * | * |
1791 | * SetGridSize -- | * SetGridSize -- |
1792 | * | * |
1793 | * This internal procedure sets the size of the grid occupied | * This internal procedure sets the size of the grid occupied |
1794 | * by slaves. | * by slaves. |
1795 | * | * |
1796 | * Results: | * Results: |
1797 | * none | * none |
1798 | * | * |
1799 | * Side effects: | * Side effects: |
1800 | * The width and height arguments are filled in the master data structure. | * The width and height arguments are filled in the master data structure. |
1801 | * Additional space is allocated for the constraints to accomodate | * Additional space is allocated for the constraints to accomodate |
1802 | * the offsets. | * the offsets. |
1803 | * | * |
1804 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1805 | */ | */ |
1806 | ||
1807 | static void | static void |
1808 | SetGridSize(masterPtr) | SetGridSize(masterPtr) |
1809 | Gridder *masterPtr; /* The geometry master for this grid. */ | Gridder *masterPtr; /* The geometry master for this grid. */ |
1810 | { | { |
1811 | register Gridder *slavePtr; /* Current slave window. */ | register Gridder *slavePtr; /* Current slave window. */ |
1812 | int maxX = 0, maxY = 0; | int maxX = 0, maxY = 0; |
1813 | ||
1814 | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; | for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; |
1815 | slavePtr = slavePtr->nextPtr) { | slavePtr = slavePtr->nextPtr) { |
1816 | maxX = MAX(maxX,slavePtr->numCols + slavePtr->column); | maxX = MAX(maxX,slavePtr->numCols + slavePtr->column); |
1817 | maxY = MAX(maxY,slavePtr->numRows + slavePtr->row); | maxY = MAX(maxY,slavePtr->numRows + slavePtr->row); |
1818 | } | } |
1819 | masterPtr->masterDataPtr->columnEnd = maxX; | masterPtr->masterDataPtr->columnEnd = maxX; |
1820 | masterPtr->masterDataPtr->rowEnd = maxY; | masterPtr->masterDataPtr->rowEnd = maxY; |
1821 | CheckSlotData(masterPtr, maxX, COLUMN, CHECK_SPACE); | CheckSlotData(masterPtr, maxX, COLUMN, CHECK_SPACE); |
1822 | CheckSlotData(masterPtr, maxY, ROW, CHECK_SPACE); | CheckSlotData(masterPtr, maxY, ROW, CHECK_SPACE); |
1823 | } | } |
1824 | ||
1825 | /* | /* |
1826 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1827 | * | * |
1828 | * CheckSlotData -- | * CheckSlotData -- |
1829 | * | * |
1830 | * This internal procedure is used to manage the storage for | * This internal procedure is used to manage the storage for |
1831 | * row and column (slot) constraints. | * row and column (slot) constraints. |
1832 | * | * |
1833 | * Results: | * Results: |
1834 | * TRUE if the index is OK, False otherwise. | * TRUE if the index is OK, False otherwise. |
1835 | * | * |
1836 | * Side effects: | * Side effects: |
1837 | * A new master grid structure may be created. If so, then | * A new master grid structure may be created. If so, then |
1838 | * it is initialized. In addition, additional storage for | * it is initialized. In addition, additional storage for |
1839 | * a row or column constraints may be allocated, and the constraint | * a row or column constraints may be allocated, and the constraint |
1840 | * maximums are adjusted. | * maximums are adjusted. |
1841 | * | * |
1842 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1843 | */ | */ |
1844 | ||
1845 | static int | static int |
1846 | CheckSlotData(masterPtr, slot, slotType, checkOnly) | CheckSlotData(masterPtr, slot, slotType, checkOnly) |
1847 | Gridder *masterPtr; /* the geometry master for this grid */ | Gridder *masterPtr; /* the geometry master for this grid */ |
1848 | int slot; /* which slot to look at */ | int slot; /* which slot to look at */ |
1849 | int slotType; /* ROW or COLUMN */ | int slotType; /* ROW or COLUMN */ |
1850 | int checkOnly; /* don't allocate new space if true */ | int checkOnly; /* don't allocate new space if true */ |
1851 | { | { |
1852 | int numSlot; /* number of slots already allocated (Space) */ | int numSlot; /* number of slots already allocated (Space) */ |
1853 | int end; /* last used constraint */ | int end; /* last used constraint */ |
1854 | ||
1855 | /* | /* |
1856 | * If slot is out of bounds, return immediately. | * If slot is out of bounds, return immediately. |
1857 | */ | */ |
1858 | ||
1859 | if (slot < 0 || slot >= MAX_ELEMENT) { | if (slot < 0 || slot >= MAX_ELEMENT) { |
1860 | return TCL_ERROR; | return TCL_ERROR; |
1861 | } | } |
1862 | ||
1863 | if ((checkOnly == CHECK_ONLY) && (masterPtr->masterDataPtr == NULL)) { | if ((checkOnly == CHECK_ONLY) && (masterPtr->masterDataPtr == NULL)) { |
1864 | return TCL_ERROR; | return TCL_ERROR; |
1865 | } | } |
1866 | ||
1867 | /* | /* |
1868 | * If we need to allocate more space, allocate a little extra to avoid | * If we need to allocate more space, allocate a little extra to avoid |
1869 | * repeated re-alloc's for large tables. We need enough space to | * repeated re-alloc's for large tables. We need enough space to |
1870 | * hold all of the offsets as well. | * hold all of the offsets as well. |
1871 | */ | */ |
1872 | ||
1873 | InitMasterData(masterPtr); | InitMasterData(masterPtr); |
1874 | end = (slotType == ROW) ? masterPtr->masterDataPtr->rowMax : | end = (slotType == ROW) ? masterPtr->masterDataPtr->rowMax : |
1875 | masterPtr->masterDataPtr->columnMax; | masterPtr->masterDataPtr->columnMax; |
1876 | if (checkOnly == CHECK_ONLY) { | if (checkOnly == CHECK_ONLY) { |
1877 | return (end < slot) ? TCL_ERROR : TCL_OK; | return (end < slot) ? TCL_ERROR : TCL_OK; |
1878 | } else { | } else { |
1879 | numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace | numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace |
1880 | : masterPtr->masterDataPtr->columnSpace; | : masterPtr->masterDataPtr->columnSpace; |
1881 | if (slot >= numSlot) { | if (slot >= numSlot) { |
1882 | int newNumSlot = slot + PREALLOC ; | int newNumSlot = slot + PREALLOC ; |
1883 | size_t oldSize = numSlot * sizeof(SlotInfo) ; | size_t oldSize = numSlot * sizeof(SlotInfo) ; |
1884 | size_t newSize = newNumSlot * sizeof(SlotInfo) ; | size_t newSize = newNumSlot * sizeof(SlotInfo) ; |
1885 | SlotInfo *new = (SlotInfo *) ckalloc(newSize); | SlotInfo *new = (SlotInfo *) ckalloc(newSize); |
1886 | SlotInfo *old = (slotType == ROW) ? | SlotInfo *old = (slotType == ROW) ? |
1887 | masterPtr->masterDataPtr->rowPtr : | masterPtr->masterDataPtr->rowPtr : |
1888 | masterPtr->masterDataPtr->columnPtr; | masterPtr->masterDataPtr->columnPtr; |
1889 | memcpy((VOID *) new, (VOID *) old, oldSize ); | memcpy((VOID *) new, (VOID *) old, oldSize ); |
1890 | memset((VOID *) (new+numSlot), 0, newSize - oldSize ); | memset((VOID *) (new+numSlot), 0, newSize - oldSize ); |
1891 | Tcl_Free((char *) old); | Tcl_Free((char *) old); |
1892 | if (slotType == ROW) { | if (slotType == ROW) { |
1893 | masterPtr->masterDataPtr->rowPtr = new ; | masterPtr->masterDataPtr->rowPtr = new ; |
1894 | masterPtr->masterDataPtr->rowSpace = newNumSlot ; | masterPtr->masterDataPtr->rowSpace = newNumSlot ; |
1895 | } else { | } else { |
1896 | masterPtr->masterDataPtr->columnPtr = new; | masterPtr->masterDataPtr->columnPtr = new; |
1897 | masterPtr->masterDataPtr->columnSpace = newNumSlot ; | masterPtr->masterDataPtr->columnSpace = newNumSlot ; |
1898 | } | } |
1899 | } | } |
1900 | if (slot >= end && checkOnly != CHECK_SPACE) { | if (slot >= end && checkOnly != CHECK_SPACE) { |
1901 | if (slotType == ROW) { | if (slotType == ROW) { |
1902 | masterPtr->masterDataPtr->rowMax = slot+1; | masterPtr->masterDataPtr->rowMax = slot+1; |
1903 | } else { | } else { |
1904 | masterPtr->masterDataPtr->columnMax = slot+1; | masterPtr->masterDataPtr->columnMax = slot+1; |
1905 | } | } |
1906 | } | } |
1907 | return TCL_OK; | return TCL_OK; |
1908 | } | } |
1909 | } | } |
1910 | ||
1911 | /* | /* |
1912 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1913 | * | * |
1914 | * InitMasterData -- | * InitMasterData -- |
1915 | * | * |
1916 | * This internal procedure is used to allocate and initialize | * This internal procedure is used to allocate and initialize |
1917 | * the data for a geometry master, if the data | * the data for a geometry master, if the data |
1918 | * doesn't exist already. | * doesn't exist already. |
1919 | * | * |
1920 | * Results: | * Results: |
1921 | * none | * none |
1922 | * | * |
1923 | * Side effects: | * Side effects: |
1924 | * A new master grid structure may be created. If so, then | * A new master grid structure may be created. If so, then |
1925 | * it is initialized. | * it is initialized. |
1926 | * | * |
1927 | *-------------------------------------------------------------- | *-------------------------------------------------------------- |
1928 | */ | */ |
1929 | ||
1930 | static void | static void |
1931 | InitMasterData(masterPtr) | InitMasterData(masterPtr) |
1932 | Gridder *masterPtr; | Gridder *masterPtr; |
1933 | { | { |
1934 | size_t size; | size_t size; |
1935 | if (masterPtr->masterDataPtr == NULL) { | if (masterPtr->masterDataPtr == NULL) { |
1936 | GridMaster *gridPtr = masterPtr->masterDataPtr = | GridMaster *gridPtr = masterPtr->masterDataPtr = |
1937 | (GridMaster *) ckalloc(sizeof(GridMaster)); | (GridMaster *) ckalloc(sizeof(GridMaster)); |
1938 | size = sizeof(SlotInfo) * TYPICAL_SIZE; | size = sizeof(SlotInfo) * TYPICAL_SIZE; |
1939 | ||
1940 | gridPtr->columnEnd = 0; | gridPtr->columnEnd = 0; |
1941 | gridPtr->columnMax = 0; | gridPtr->columnMax = 0; |
1942 | gridPtr->columnPtr = (SlotInfo *) ckalloc(size); | gridPtr->columnPtr = (SlotInfo *) ckalloc(size); |
1943 | gridPtr->columnSpace = TYPICAL_SIZE; | gridPtr->columnSpace = TYPICAL_SIZE; |
1944 | gridPtr->rowEnd = 0; | gridPtr->rowEnd = 0; |
1945 | gridPtr->rowMax = 0; | gridPtr->rowMax = 0; |
1946 | gridPtr->rowPtr = (SlotInfo *) ckalloc(size); | gridPtr->rowPtr = (SlotInfo *) ckalloc(size); |
1947 | gridPtr->rowSpace = TYPICAL_SIZE; | gridPtr->rowSpace = TYPICAL_SIZE; |
1948 | gridPtr->startX = 0; | gridPtr->startX = 0; |
1949 | gridPtr->startY = 0; | gridPtr->startY = 0; |
1950 | ||
1951 | memset((VOID *) gridPtr->columnPtr, 0, size); | memset((VOID *) gridPtr->columnPtr, 0, size); |
1952 | memset((VOID *) gridPtr->rowPtr, 0, size); | memset((VOID *) gridPtr->rowPtr, 0, size); |
1953 | } | } |
1954 | } | } |
1955 | ||
1956 | /* | /* |
1957 | *---------------------------------------------------------------------- | *---------------------------------------------------------------------- |
1958 | * | * |
1959 | * Unlink -- | * Unlink -- |
1960 | * | * |
1961 | * Remove a grid from its parent's list of slaves. | * Remove a grid from its parent's list of slaves. |
1962 | * | * |
1963 | * Results: | * Results: |
1964 | * None. | * None. |
1965 | * | * |
1966 | * Side effects: | * Side effects: |
1967 | * The parent will be scheduled for re-arranging, and the size of the | * The parent will be scheduled for re-arranging, and the size of the |
1968 | * grid will be adjusted accordingly | * grid will be adjusted accordingly |
1969 | * | * |
1970 | *---------------------------------------------------------------------- | *---------------------------------------------------------------------- |
1971 | */ | */ |
1972 | ||
1973 | static void | static void |
1974 | Unlink(slavePtr) | Unlink(slavePtr) |
1975 | register Gridder *slavePtr; /* Window to unlink. */ | register Gridder *slavePtr; /* Window to unlink. */ |
1976 | { | { |
1977 | register Gridder *masterPtr, *slavePtr2; | register Gridder *masterPtr, *slavePtr2; |
1978 | GridMaster *gridPtr; /* pointer to grid data */ | GridMaster *gridPtr; /* pointer to grid data */ |
1979 | ||
1980 | masterPtr = slavePtr->masterPtr; | masterPtr = slavePtr->masterPtr; |
1981 | if (masterPtr == NULL) { | if (masterPtr == NULL) { |
1982 | return; | return; |
1983 | } | } |
1984 | ||
1985 | gridPtr = masterPtr->masterDataPtr; | gridPtr = masterPtr->masterDataPtr; |
1986 | if (masterPtr->slavePtr == slavePtr) { | if (masterPtr->slavePtr == slavePtr) { |
1987 | masterPtr->slavePtr = slavePtr->nextPtr; | masterPtr->slavePtr = slavePtr->nextPtr; |
1988 | } | } |
1989 | else { | else { |
1990 | for (slavePtr2 = masterPtr->slavePtr; ; slavePtr2 = slavePtr2->nextPtr) { | for (slavePtr2 = masterPtr->slavePtr; ; slavePtr2 = slavePtr2->nextPtr) { |
1991 | if (slavePtr2 == NULL) { | if (slavePtr2 == NULL) { |
1992 | panic("Unlink couldn't find previous window"); | panic("Unlink couldn't find previous window"); |
1993 | } | } |
1994 | if (slavePtr2->nextPtr == slavePtr) { | if (slavePtr2->nextPtr == slavePtr) { |
1995 | slavePtr2->nextPtr = slavePtr->nextPtr; | slavePtr2->nextPtr = slavePtr->nextPtr; |
1996 | break; | break; |
1997 | } | } |
1998 | } | } |
1999 | } | } |
2000 | if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { | if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { |
2001 | masterPtr->flags |= REQUESTED_RELAYOUT; | masterPtr->flags |= REQUESTED_RELAYOUT; |
2002 | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); |
2003 | } | } |
2004 | if (masterPtr->abortPtr != NULL) { | if (masterPtr->abortPtr != NULL) { |
2005 | *masterPtr->abortPtr = 1; | *masterPtr->abortPtr = 1; |
2006 | } | } |
2007 | ||
2008 | if ((slavePtr->numCols+slavePtr->column == gridPtr->columnMax) | if ((slavePtr->numCols+slavePtr->column == gridPtr->columnMax) |
2009 | || (slavePtr->numRows+slavePtr->row == gridPtr->rowMax)) { | || (slavePtr->numRows+slavePtr->row == gridPtr->rowMax)) { |
2010 | } | } |
2011 | slavePtr->masterPtr = NULL; | slavePtr->masterPtr = NULL; |
2012 | } | } |
2013 | ||
2014 | /* | /* |
2015 | *---------------------------------------------------------------------- | *---------------------------------------------------------------------- |
2016 | * | * |
2017 | * DestroyGrid -- | * DestroyGrid -- |
2018 | * | * |
2019 | * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release | * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release |
2020 | * to clean up the internal structure of a grid at a safe time | * to clean up the internal structure of a grid at a safe time |
2021 | * (when no-one is using it anymore). Cleaning up the grid involves | * (when no-one is using it anymore). Cleaning up the grid involves |
2022 | * freeing the main structure for all windows. and the master structure | * freeing the main structure for all windows. and the master structure |
2023 | * for geometry managers. | * for geometry managers. |
2024 | * | * |
2025 | * Results: | * Results: |
2026 | * None. | * None. |
2027 | * | * |
2028 | * Side effects: | * Side effects: |
2029 | * Everything associated with the grid is freed up. | * Everything associated with the grid is freed up. |
2030 | * | * |
2031 | *---------------------------------------------------------------------- | *---------------------------------------------------------------------- |
2032 | */ | */ |
2033 | ||
2034 | static void | static void |
2035 | DestroyGrid(memPtr) | DestroyGrid(memPtr) |
2036 | char *memPtr; /* Info about window that is now dead. */ | char *memPtr; /* Info about window that is now dead. */ |
2037 | { | { |
2038 | register Gridder *gridPtr = (Gridder *) memPtr; | register Gridder *gridPtr = (Gridder *) memPtr; |
2039 | ||
2040 | if (gridPtr->masterDataPtr != NULL) { | if (gridPtr->masterDataPtr != NULL) { |
2041 | if (gridPtr->masterDataPtr->rowPtr != NULL) { | if (gridPtr->masterDataPtr->rowPtr != NULL) { |
2042 | Tcl_Free((char *) gridPtr->masterDataPtr -> rowPtr); | Tcl_Free((char *) gridPtr->masterDataPtr -> rowPtr); |
2043 | } | } |
2044 | if (gridPtr->masterDataPtr->columnPtr != NULL) { | if (gridPtr->masterDataPtr->columnPtr != NULL) { |
2045 | Tcl_Free((char *) gridPtr->masterDataPtr -> columnPtr); | Tcl_Free((char *) gridPtr->masterDataPtr -> columnPtr); |
2046 | } | } |
2047 | Tcl_Free((char *) gridPtr->masterDataPtr); | Tcl_Free((char *) gridPtr->masterDataPtr); |
2048 | } | } |
2049 | Tcl_Free((char *) gridPtr); | Tcl_Free((char *) gridPtr); |
2050 | } | } |
2051 | ||
2052 | /* | /* |
2053 | *---------------------------------------------------------------------- | *---------------------------------------------------------------------- |
2054 | * | * |
2055 | * GridStructureProc -- | * GridStructureProc -- |
2056 | * | * |
2057 | * This procedure is invoked by the Tk event dispatcher in response | * This procedure is invoked by the Tk event dispatcher in response |
2058 | * to StructureNotify events. | * to StructureNotify events. |
2059 | * | * |
2060 | * Results: | * Results: |
2061 | * None. | * None. |
2062 | * | * |
2063 | * Side effects: | * Side effects: |
2064 | * If a window was just deleted, clean up all its grid-related | * If a window was just deleted, clean up all its grid-related |
2065 | * information. If it was just resized, re-configure its slaves, if | * information. If it was just resized, re-configure its slaves, if |
2066 | * any. | * any. |
2067 | * | * |
2068 | *---------------------------------------------------------------------- | *---------------------------------------------------------------------- |
2069 | */ | */ |
2070 | ||
2071 | static void | static void |
2072 | GridStructureProc(clientData, eventPtr) | GridStructureProc(clientData, eventPtr) |
2073 | ClientData clientData; /* Our information about window | ClientData clientData; /* Our information about window |
2074 | * referred to by eventPtr. */ | * referred to by eventPtr. */ |
2075 | XEvent *eventPtr; /* Describes what just happened. */ | XEvent *eventPtr; /* Describes what just happened. */ |
2076 | { | { |
2077 | register Gridder *gridPtr = (Gridder *) clientData; | register Gridder *gridPtr = (Gridder *) clientData; |
2078 | TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr; | TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr; |
2079 | ||
2080 | if (eventPtr->type == ConfigureNotify) { | if (eventPtr->type == ConfigureNotify) { |
2081 | if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { | if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { |
2082 | gridPtr->flags |= REQUESTED_RELAYOUT; | gridPtr->flags |= REQUESTED_RELAYOUT; |
2083 | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); |
2084 | } | } |
2085 | if (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width) { | if (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width) { |
2086 | if ((gridPtr->masterPtr != NULL) && | if ((gridPtr->masterPtr != NULL) && |
2087 | !(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) { | !(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) { |
2088 | gridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width; | gridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width; |
2089 | gridPtr->masterPtr->flags |= REQUESTED_RELAYOUT; | gridPtr->masterPtr->flags |= REQUESTED_RELAYOUT; |
2090 | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr->masterPtr); | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr->masterPtr); |
2091 | } | } |
2092 | } | } |
2093 | } else if (eventPtr->type == DestroyNotify) { | } else if (eventPtr->type == DestroyNotify) { |
2094 | register Gridder *gridPtr2, *nextPtr; | register Gridder *gridPtr2, *nextPtr; |
2095 | ||
2096 | if (gridPtr->masterPtr != NULL) { | if (gridPtr->masterPtr != NULL) { |
2097 | Unlink(gridPtr); | Unlink(gridPtr); |
2098 | } | } |
2099 | for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; | for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; |
2100 | gridPtr2 = nextPtr) { | gridPtr2 = nextPtr) { |
2101 | Tk_UnmapWindow(gridPtr2->tkwin); | Tk_UnmapWindow(gridPtr2->tkwin); |
2102 | gridPtr2->masterPtr = NULL; | gridPtr2->masterPtr = NULL; |
2103 | nextPtr = gridPtr2->nextPtr; | nextPtr = gridPtr2->nextPtr; |
2104 | gridPtr2->nextPtr = NULL; | gridPtr2->nextPtr = NULL; |
2105 | } | } |
2106 | Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable, | Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable, |
2107 | (char *) gridPtr->tkwin)); | (char *) gridPtr->tkwin)); |
2108 | if (gridPtr->flags & REQUESTED_RELAYOUT) { | if (gridPtr->flags & REQUESTED_RELAYOUT) { |
2109 | Tcl_CancelIdleCall(ArrangeGrid, (ClientData) gridPtr); | Tcl_CancelIdleCall(ArrangeGrid, (ClientData) gridPtr); |
2110 | } | } |
2111 | gridPtr->tkwin = NULL; | gridPtr->tkwin = NULL; |
2112 | Tcl_EventuallyFree((ClientData) gridPtr, DestroyGrid); | Tcl_EventuallyFree((ClientData) gridPtr, DestroyGrid); |
2113 | } else if (eventPtr->type == MapNotify) { | } else if (eventPtr->type == MapNotify) { |
2114 | if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { | if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { |
2115 | gridPtr->flags |= REQUESTED_RELAYOUT; | gridPtr->flags |= REQUESTED_RELAYOUT; |
2116 | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); | Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); |
2117 | } | } |
2118 | } else if (eventPtr->type == UnmapNotify) { | } else if (eventPtr->type == UnmapNotify) { |
2119 | register Gridder *gridPtr2; | register Gridder *gridPtr2; |
2120 | ||
2121 | for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; | for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; |
2122 | gridPtr2 = gridPtr2->nextPtr) { | gridPtr2 = gridPtr2->nextPtr) { |
2123 | Tk_UnmapWindow(gridPtr2->tkwin); | Tk_UnmapWindow(gridPtr2->tkwin); |
2124 | } | } |
2125 | } | } |
2126 | } | } |
2127 | ||
2128 | /* | /* |
2129 | *---------------------------------------------------------------------- | *---------------------------------------------------------------------- |
2130 | * | * |
2131 | * ConfigureSlaves -- | * ConfigureSlaves -- |
2132 | * | * |
2133 | * This implements the guts of the "grid configure" command. Given | * This implements the guts of the "grid configure" command. Given |
2134 | * a list of slaves and configuration options, it arranges for the | * a list of slaves and configuration options, it arranges for the |
2135 | * grid to manage the slaves and sets the specified options. | * grid to manage the slaves and sets the specified options. |
2136 | * arguments consist of windows or window shortcuts followed by | * arguments consist of windows or window shortcuts followed by |
2137 | * "-option value" pairs. | * "-option value" pairs. |
2138 | * | * |
2139 | * Results: | * Results: |
2140 | * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is | * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is |
2141 | * returned and the interp's result is set to contain an error message. | * returned and the interp's result is set to contain an error message. |
2142 | * | * |
2143 | * Side effects: | * Side effects: |
2144 | * Slave windows get taken over by the grid. | * Slave windows get taken over by the grid. |
2145 | * | * |
2146 | *---------------------------------------------------------------------- | *---------------------------------------------------------------------- |
2147 | */ | */ |
2148 | ||
2149 | static int | static int |
2150 | ConfigureSlaves(interp, tkwin, argc, argv) | ConfigureSlaves(interp, tkwin, argc, argv) |
2151 | Tcl_Interp *interp; /* Interpreter for error reporting. */ | Tcl_Interp *interp; /* Interpreter for error reporting. */ |
2152 | Tk_Window tkwin; /* Any window in application containing | Tk_Window tkwin; /* Any window in application containing |
2153 | * slaves. Used to look up slave names. */ | * slaves. Used to look up slave names. */ |
2154 | int argc; /* Number of elements in argv. */ | int argc; /* Number of elements in argv. */ |
2155 | char *argv[]; /* Argument strings: contains one or more | char *argv[]; /* Argument strings: contains one or more |
2156 | * window names followed by any number | * window names followed by any number |
2157 | * of "option value" pairs. Caller must | * of "option value" pairs. Caller must |
2158 | * make sure that there is at least one | * make sure that there is at least one |
2159 | * window name. */ | * window name. */ |
2160 | { | { |
2161 | Gridder *masterPtr; | Gridder *masterPtr; |
2162 | Gridder *slavePtr; | Gridder *slavePtr; |
2163 | Tk_Window other, slave, parent, ancestor; | Tk_Window other, slave, parent, ancestor; |
2164 | int i, j, c, tmp; | int i, j, c, tmp; |
2165 | size_t length; | size_t length; |
2166 | int numWindows; | int numWindows; |
2167 | int width; | int width; |
2168 | int defaultColumn = 0; /* default column number */ | int defaultColumn = 0; /* default column number */ |
2169 | int defaultColumnSpan = 1; /* default number of columns */ | int defaultColumnSpan = 1; /* default number of columns */ |
2170 | char *lastWindow; /* use this window to base current | char *lastWindow; /* use this window to base current |
2171 | * Row/col on */ | * Row/col on */ |
2172 | ||
2173 | /* | /* |
2174 | * Count the number of windows, or window short-cuts. | * Count the number of windows, or window short-cuts. |
2175 | */ | */ |
2176 | ||
2177 | for(numWindows=i=0;i<argc;i++) { | for(numWindows=i=0;i<argc;i++) { |
2178 | char firstChar = *argv[i]; | char firstChar = *argv[i]; |
2179 | if (firstChar == '.') { | if (firstChar == '.') { |
2180 | numWindows++; | numWindows++; |
2181 | continue; | continue; |
2182 | } | } |
2183 | length = strlen(argv[i]); | length = strlen(argv[i]); |
2184 | if (length > 1 && firstChar == '-') { | if (length > 1 && firstChar == '-') { |
2185 | break; | break; |
2186 | } | } |
2187 | if (length > 1) { | if (length > 1) { |
2188 | Tcl_AppendResult(interp, "unexpected parameter, \"", | Tcl_AppendResult(interp, "unexpected parameter, \"", |
2189 | argv[i], "\", in configure list. ", | argv[i], "\", in configure list. ", |
2190 | "Should be window name or option", (char *) NULL); | "Should be window name or option", (char *) NULL); |
2191 | return TCL_ERROR; | return TCL_ERROR; |
2192 | } | } |
2193 | ||
2194 | if ((firstChar == REL_HORIZ) && ((numWindows == 0) || | if ((firstChar == REL_HORIZ) && ((numWindows == 0) || |
2195 | (*argv[i-1] == REL_SKIP) || (*argv[i-1] == REL_VERT))) { | (*argv[i-1] == REL_SKIP) || (*argv[i-1] == REL_VERT))) { |
2196 | Tcl_AppendResult(interp, | Tcl_AppendResult(interp, |
2197 | "Must specify window before shortcut '-'.", | "Must specify window before shortcut '-'.", |
2198 | (char *) NULL); | (char *) NULL); |
2199 | return TCL_ERROR; | return TCL_ERROR; |
2200 | } | } |
2201 | ||
2202 | if ((firstChar == REL_VERT) || (firstChar == REL_SKIP) | if ((firstChar == REL_VERT) || (firstChar == REL_SKIP) |
2203 | || (firstChar == REL_HORIZ)) { | || (firstChar == REL_HORIZ)) { |
2204 | continue; | continue; |
2205 | } | } |
2206 | ||
2207 | Tcl_AppendResult(interp, "invalid window shortcut, \"", | Tcl_AppendResult(interp, "invalid window shortcut, \"", |
2208 | argv[i], "\" should be '-', 'x', or '^'", (char *) NULL); | argv[i], "\" should be '-', 'x', or '^'", (char *) NULL); |
2209 | return TCL_ERROR; | return TCL_ERROR; |
2210 | } | } |
2211 | numWindows = i; | numWindows = i; |
2212 | ||
2213 | if ((argc-numWindows)&1) { | if ((argc-numWindows)&1) { |
2214 | Tcl_AppendResult(interp, "extra option or", | Tcl_AppendResult(interp, "extra option or", |
2215 | " option with no value", (char *) NULL); | " option with no value", (char *) NULL); |
2216 | return TCL_ERROR; | return TCL_ERROR; |
2217 | } | } |
2218 | ||
2219 | /* | /* |
2220 | * Iterate over all of the slave windows and short-cuts, parsing | * Iterate over all of the slave windows and short-cuts, parsing |
2221 | * options for each slave. It's a bit wasteful to re-parse the | * options for each slave. It's a bit wasteful to re-parse the |
2222 | * options for each slave, but things get too messy if we try to | * options for each slave, but things get too messy if we try to |
2223 | * parse the arguments just once at the beginning. For example, | * parse the arguments just once at the beginning. For example, |
2224 | * if a slave already is managed we want to just change a few | * if a slave already is managed we want to just change a few |
2225 | * existing values without resetting everything. If there are | * existing values without resetting everything. If there are |
2226 | * multiple windows, the -in option only gets processed for the | * multiple windows, the -in option only gets processed for the |
2227 | * first window. | * first window. |
2228 | */ | */ |
2229 | ||
2230 | masterPtr = NULL; | masterPtr = NULL; |
2231 | for (j = 0; j < numWindows; j++) { | for (j = 0; j < numWindows; j++) { |
2232 | char firstChar = *argv[j]; | char firstChar = *argv[j]; |
2233 | ||
2234 | /* | /* |
2235 | * '^' and 'x' cause us to skip a column. '-' is processed | * '^' and 'x' cause us to skip a column. '-' is processed |
2236 | * as part of its preceeding slave. | * as part of its preceeding slave. |
2237 | */ | */ |
2238 | ||
2239 | if ((firstChar == REL_VERT) || (firstChar == REL_SKIP)) { | if ((firstChar == REL_VERT) || (firstChar == REL_SKIP)) { |
2240 | defaultColumn++; | defaultColumn++; |
2241 | continue; | continue; |
2242 | } | } |
2243 | if (firstChar == REL_HORIZ) { | if (firstChar == REL_HORIZ) { |
2244 | continue; | continue; |
2245 | } | } |
2246 | ||
2247 | for (defaultColumnSpan=1; | for (defaultColumnSpan=1; |
2248 | j + defaultColumnSpan < numWindows && | j + defaultColumnSpan < numWindows && |
2249 | (*argv[j+defaultColumnSpan] == REL_HORIZ); | (*argv[j+defaultColumnSpan] == REL_HORIZ); |
2250 | defaultColumnSpan++) { | defaultColumnSpan++) { |
2251 | /* null body */ | /* null body */ |
2252 | } | } |
2253 | ||
2254 | slave = Tk_NameToWindow(interp, argv[j], tkwin); | slave = Tk_NameToWindow(interp, argv[j], tkwin); |
2255 | if (slave == NULL) { | if (slave == NULL) { |
2256 | return TCL_ERROR; | return TCL_ERROR; |
2257 | } | } |
2258 | if (Tk_IsTopLevel(slave)) { | if (Tk_IsTopLevel(slave)) { |
2259 | Tcl_AppendResult(interp, "can't manage \"", argv[j], | Tcl_AppendResult(interp, "can't manage \"", argv[j], |
2260 | "\": it's a top-level window", (char *) NULL); | "\": it's a top-level window", (char *) NULL); |
2261 | return TCL_ERROR; | return TCL_ERROR; |
2262 | } | } |
2263 | slavePtr = GetGrid(slave); | slavePtr = GetGrid(slave); |
2264 | ||
2265 | /* | /* |
2266 | * The following statement is taken from tkPack.c: | * The following statement is taken from tkPack.c: |
2267 | * | * |
2268 | * "If the slave isn't currently managed, reset all of its | * "If the slave isn't currently managed, reset all of its |
2269 | * configuration information to default values (there could | * configuration information to default values (there could |
2270 | * be old values left from a previous packer)." | * be old values left from a previous packer)." |
2271 | * | * |
2272 | * I [D.S.] disagree with this statement. If a slave is disabled (using | * I [D.S.] disagree with this statement. If a slave is disabled (using |
2273 | * "forget") and then re-enabled, I submit that 90% of the time the | * "forget") and then re-enabled, I submit that 90% of the time the |
2274 | * programmer will want it to retain its old configuration information. | * programmer will want it to retain its old configuration information. |
2275 | * If the programmer doesn't want this behavior, then the | * If the programmer doesn't want this behavior, then the |
2276 | * defaults can be reestablished by hand, without having to worry | * defaults can be reestablished by hand, without having to worry |
2277 | * about keeping track of the old state. | * about keeping track of the old state. |
2278 | */ | */ |
2279 | ||
2280 | for (i = numWindows; i < argc; i+=2) { | for (i = numWindows; i < argc; i+=2) { |
2281 | length = strlen(argv[i]); | length = strlen(argv[i]); |
2282 | c = argv[i][1]; | c = argv[i][1]; |
2283 | ||
2284 | if (length < 2) { | if (length < 2) { |
2285 | Tcl_AppendResult(interp, "unknown or ambiguous option \"", | Tcl_AppendResult(interp, "unknown or ambiguous option \"", |
2286 | argv[i], "\": must be ", | argv[i], "\": must be ", |
2287 | "-column, -columnspan, -in, -ipadx, -ipady, ", | "-column, -columnspan, -in, -ipadx, -ipady, ", |
2288 | "-padx, -pady, -row, -rowspan, or -sticky", | "-padx, -pady, -row, -rowspan, or -sticky", |
2289 | (char *) NULL); | (char *) NULL); |
2290 | return TCL_ERROR; | return TCL_ERROR; |
2291 | } | } |
2292 | if ((c == 'c') && (strncmp(argv[i], "-column", length) == 0)) { | if ((c == 'c') && (strncmp(argv[i], "-column", length) == 0)) { |
2293 | if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp<0) { | if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp<0) { |
2294 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
2295 | Tcl_AppendResult(interp, "bad column value \"", argv[i+1], | Tcl_AppendResult(interp, "bad column value \"", argv[i+1], |
2296 | "\": must be a non-negative integer", (char *)NULL); | "\": must be a non-negative integer", (char *)NULL); |
2297 | return TCL_ERROR; | return TCL_ERROR; |
2298 | } | } |
2299 | slavePtr->column = tmp; | slavePtr->column = tmp; |
2300 | } else if ((c == 'c') | } else if ((c == 'c') |
2301 | && (strncmp(argv[i], "-columnspan", length) == 0)) { | && (strncmp(argv[i], "-columnspan", length) == 0)) { |
2302 | if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp <= 0) { | if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp <= 0) { |
2303 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
2304 | Tcl_AppendResult(interp, "bad columnspan value \"", argv[i+1], | Tcl_AppendResult(interp, "bad columnspan value \"", argv[i+1], |
2305 | "\": must be a positive integer", (char *)NULL); | "\": must be a positive integer", (char *)NULL); |
2306 | return TCL_ERROR; | return TCL_ERROR; |
2307 | } | } |
2308 | slavePtr->numCols = tmp; | slavePtr->numCols = tmp; |
2309 | } else if ((c == 'i') && (strncmp(argv[i], "-in", length) == 0)) { | } else if ((c == 'i') && (strncmp(argv[i], "-in", length) == 0)) { |
2310 | other = Tk_NameToWindow(interp, argv[i+1], tkwin); | other = Tk_NameToWindow(interp, argv[i+1], tkwin); |
2311 | if (other == NULL) { | if (other == NULL) { |
2312 | return TCL_ERROR; | return TCL_ERROR; |
2313 | } | } |
2314 | if (other == slave) { | if (other == slave) { |
2315 | Tcl_SetResult(interp, "Window can't be managed in itself", | Tcl_SetResult(interp, "Window can't be managed in itself", |
2316 | TCL_STATIC); | TCL_STATIC); |
2317 | return TCL_ERROR; | return TCL_ERROR; |
2318 | } | } |
2319 | masterPtr = GetGrid(other); | masterPtr = GetGrid(other); |
2320 | InitMasterData(masterPtr); | InitMasterData(masterPtr); |
2321 | } else if ((c == 'i') | } else if ((c == 'i') |
2322 | && (strncmp(argv[i], "-ipadx", length) == 0)) { | && (strncmp(argv[i], "-ipadx", length) == 0)) { |
2323 | if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) | if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) |
2324 | || (tmp < 0)) { | || (tmp < 0)) { |
2325 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
2326 | Tcl_AppendResult(interp, "bad ipadx value \"", argv[i+1], | Tcl_AppendResult(interp, "bad ipadx value \"", argv[i+1], |
2327 | "\": must be positive screen distance", | "\": must be positive screen distance", |
2328 | (char *) NULL); | (char *) NULL); |
2329 | return TCL_ERROR; | return TCL_ERROR; |
2330 | } | } |
2331 | slavePtr->iPadX = tmp*2; | slavePtr->iPadX = tmp*2; |
2332 | } else if ((c == 'i') | } else if ((c == 'i') |
2333 | && (strncmp(argv[i], "-ipady", length) == 0)) { | && (strncmp(argv[i], "-ipady", length) == 0)) { |
2334 | if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) | if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) |
2335 | || (tmp< 0)) { | || (tmp< 0)) { |
2336 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
2337 | Tcl_AppendResult(interp, "bad ipady value \"", argv[i+1], | Tcl_AppendResult(interp, "bad ipady value \"", argv[i+1], |
2338 | "\": must be positive screen distance", | "\": must be positive screen distance", |
2339 | (char *) NULL); | (char *) NULL); |
2340 | return TCL_ERROR; | return TCL_ERROR; |
2341 | } | } |
2342 | slavePtr->iPadY = tmp*2; | slavePtr->iPadY = tmp*2; |
2343 | } else if ((c == 'p') | } else if ((c == 'p') |
2344 | && (strncmp(argv[i], "-padx", length) == 0)) { | && (strncmp(argv[i], "-padx", length) == 0)) { |
2345 | if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) | if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) |
2346 | || (tmp< 0)) { | || (tmp< 0)) { |
2347 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
2348 | Tcl_AppendResult(interp, "bad padx value \"", argv[i+1], | Tcl_AppendResult(interp, "bad padx value \"", argv[i+1], |
2349 | "\": must be positive screen distance", | "\": must be positive screen distance", |
2350 | (char *) NULL); | (char *) NULL); |
2351 | return TCL_ERROR; | return TCL_ERROR; |
2352 | } | } |
2353 | slavePtr->padX = tmp*2; | slavePtr->padX = tmp*2; |
2354 | } else if ((c == 'p') | } else if ((c == 'p') |
2355 | && (strncmp(argv[i], "-pady", length) == 0)) { | && (strncmp(argv[i], "-pady", length) == 0)) { |
2356 | if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) | if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) |
2357 | || (tmp< 0)) { | || (tmp< 0)) { |
2358 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
2359 | Tcl_AppendResult(interp, "bad pady value \"", argv[i+1], | Tcl_AppendResult(interp, "bad pady value \"", argv[i+1], |
2360 | "\": must be positive screen distance", | "\": must be positive screen distance", |
2361 | (char *) NULL); | (char *) NULL); |
2362 | return TCL_ERROR; | return TCL_ERROR; |
2363 | } | } |
2364 | slavePtr->padY = tmp*2; | slavePtr->padY = tmp*2; |
2365 | } else if ((c == 'r') && (strncmp(argv[i], "-row", length) == 0)) { | } else if ((c == 'r') && (strncmp(argv[i], "-row", length) == 0)) { |
2366 | if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp<0) { | if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp<0) { |
2367 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
2368 | Tcl_AppendResult(interp, "bad grid value \"", argv[i+1], | Tcl_AppendResult(interp, "bad grid value \"", argv[i+1], |
2369 | "\": must be a non-negative integer", (char *)NULL); | "\": must be a non-negative integer", (char *)NULL); |
2370 | return TCL_ERROR; | return TCL_ERROR; |
2371 | } | } |
2372 | slavePtr->row = tmp; | slavePtr->row = tmp; |
2373 | } else if ((c == 'r') | } else if ((c == 'r') |
2374 | && (strncmp(argv[i], "-rowspan", length) == 0)) { | && (strncmp(argv[i], "-rowspan", length) == 0)) { |
2375 | if ((Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK) || tmp<=0) { | if ((Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK) || tmp<=0) { |
2376 | Tcl_ResetResult(interp); | Tcl_ResetResult(interp); |
2377 | Tcl_AppendResult(interp, "bad rowspan value \"", argv[i+1], | Tcl_AppendResult(interp, "bad rowspan value \"", argv[i+1], |
2378 | "\": must be a positive integer", (char *)NULL); | "\": must be a positive integer", (char *)NULL); |
2379 | return TCL_ERROR; | return TCL_ERROR; |
2380 | } | } |
2381 | slavePtr->numRows = tmp; | slavePtr->numRows = tmp; |
2382 | } else if ((c == 's') | } else if ((c == 's') |
2383 | && strncmp(argv[i], "-sticky", length) == 0) { | && strncmp(argv[i], "-sticky", length) == 0) { |
2384 | int sticky = StringToSticky(argv[i+1]); | int sticky = StringToSticky(argv[i+1]); |
2385 | if (sticky == -1) { | if (sticky == -1) { |
2386 | Tcl_AppendResult(interp, "bad stickyness value \"", argv[i+1], | Tcl_AppendResult(interp, "bad stickyness value \"", argv[i+1], |
2387 | "\": must be a string containing n, e, s, and/or w", | "\": must be a string containing n, e, s, and/or w", |
2388 | (char *)NULL); | (char *)NULL); |
2389 | return TCL_ERROR; | return TCL_ERROR; |
2390 | } | } |
2391 | slavePtr->sticky = sticky; | slavePtr->sticky = sticky; |
2392 | } else { | } else { |
2393 | Tcl_AppendResult(interp, "unknown or ambiguous option \"", | Tcl_AppendResult(interp, "unknown or ambiguous option \"", |
2394 | argv[i], "\": must be ", | argv[i], "\": must be ", |
2395 | "-column, -columnspan, -in, -ipadx, -ipady, ", | "-column, -columnspan, -in, -ipadx, -ipady, ", |
2396 | "-padx, -pady, -row, -rowspan, or -sticky", | "-padx, -pady, -row, -rowspan, or -sticky", |
2397 | (char *) NULL); | (char *) NULL); |
2398 | return TCL_ERROR; | return TCL_ERROR; |
2399 | } | } |
2400 | } | } |
2401 | ||
2402 | /* | /* |
2403 | * Make sure we have a geometry master. We look at: | * Make sure we have a geometry master. We look at: |
2404 | * 1) the -in flag | * 1) the -in flag |
2405 | * 2) the geometry master of the first slave (if specified) | * 2) the geometry master of the first slave (if specified) |
2406 | * 3) the parent of the first slave. | * 3) the parent of the first slave. |
2407 | */ | */ |
2408 | ||
2409 | if (masterPtr == NULL) { | if (masterPtr == NULL) { |
2410 | masterPtr = slavePtr->masterPtr; | masterPtr = slavePtr->masterPtr; |
2411 | } | } |
2412 | parent = Tk_Parent(slave); | parent = Tk_Parent(slave); |
2413 | if (masterPtr == NULL) { | if (masterPtr == NULL) { |
2414 | masterPtr = GetGrid(parent); | masterPtr = GetGrid(parent); |
2415 | InitMasterData(masterPtr); | InitMasterData(masterPtr); |
2416 | } | } |
2417 | ||
2418 | if (slavePtr->masterPtr != NULL && slavePtr->masterPtr != masterPtr) { | if (slavePtr->masterPtr != NULL && slavePtr->masterPtr != masterPtr) { |
2419 | Unlink(slavePtr); | Unlink(slavePtr); |
2420 | slavePtr->masterPtr = NULL; | slavePtr->masterPtr = NULL; |
2421 | } | } |
2422 | ||
2423 | if (slavePtr->masterPtr == NULL) { | if (slavePtr->masterPtr == NULL) { |
2424 | Gridder *tempPtr = masterPtr->slavePtr; | Gridder *tempPtr = masterPtr->slavePtr; |
2425 | slavePtr->masterPtr = masterPtr; | slavePtr->masterPtr = masterPtr; |
2426 | masterPtr->slavePtr = slavePtr; | masterPtr->slavePtr = slavePtr; |
2427 | slavePtr->nextPtr = tempPtr; | slavePtr->nextPtr = tempPtr; |
2428 | } | } |
2429 | ||
2430 | /* | /* |
2431 | * Make sure that the slave's parent is either the master or | * Make sure that the slave's parent is either the master or |
2432 | * an ancestor of the master, and that the master and slave | * an ancestor of the master, and that the master and slave |
2433 | * aren't the same. | * aren't the same. |
2434 | */ | */ |
2435 | ||
2436 | for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { | for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { |
2437 | if (ancestor == parent) { | if (ancestor == parent) { |
2438 | break; | break; |
2439 | } | } |
2440 | if (Tk_IsTopLevel(ancestor)) { | if (Tk_IsTopLevel(ancestor)) { |
2441 | Tcl_AppendResult(interp, "can't put ", argv[j], | Tcl_AppendResult(interp, "can't put ", argv[j], |
2442 | " inside ", Tk_PathName(masterPtr->tkwin), | " inside ", Tk_PathName(masterPtr->tkwin), |
2443 | (char *) NULL); | (char *) NULL); |
2444 | Unlink(slavePtr); | Unlink(slavePtr); |
2445 | return TCL_ERROR; | return TCL_ERROR; |
2446 | } | } |
2447 | } | } |
2448 | ||
2449 | /* | /* |
2450 | * Try to make sure our master isn't managed by us. | * Try to make sure our master isn't managed by us. |
2451 | */ | */ |
2452 | ||
2453 | if (masterPtr->masterPtr == slavePtr) { | if (masterPtr->masterPtr == slavePtr) { |
2454 | Tcl_AppendResult(interp, "can't put ", argv[j], | Tcl_AppendResult(interp, "can't put ", argv[j], |
2455 | " inside ", Tk_PathName(masterPtr->tkwin), | " inside ", Tk_PathName(masterPtr->tkwin), |
2456 | ", would cause management loop.", | ", would cause management loop.", |
2457 | (char *) NULL); | (char *) NULL); |
2458 | Unlink(slavePtr); | Unlink(slavePtr); |
2459 | return TCL_ERROR; | return TCL_ERROR; |
2460 | } | } |
2461 | ||
2462 | Tk_ManageGeometry(slave, &gridMgrType, (ClientData) slavePtr); | Tk_ManageGeometry(slave, &gridMgrType, (ClientData) slavePtr); |
2463 | ||
2464 | /* | /* |
2465 | * Assign default position information. | * Assign default position information. |
2466 | */ | */ |
2467 | ||
2468 | if (slavePtr->column == -1) { | if (slavePtr->column == -1) { |
2469 | slavePtr->column = defaultColumn; | slavePtr->column = defaultColumn; |
2470 | } | } |
2471 | slavePtr->numCols += defaultColumnSpan - 1; | slavePtr->numCols += defaultColumnSpan - 1; |
2472 | if (slavePtr->row == -1) { | if (slavePtr->row == -1) { |
2473 | if (masterPtr->masterDataPtr == NULL) { | if (masterPtr->masterDataPtr == NULL) { |
2474 | slavePtr->row = 0; | slavePtr->row = 0; |
2475 | } else { | } else { |
2476 | slavePtr->row = masterPtr->masterDataPtr->rowEnd; | slavePtr->row = masterPtr->masterDataPtr->rowEnd; |
2477 | } | } |
2478 | } | } |
2479 | defaultColumn += slavePtr->numCols; | defaultColumn += slavePtr->numCols; |
2480 | defaultColumnSpan = 1; | defaultColumnSpan = 1; |
2481 | ||