1 
2 /*	$Id: tixFormMisc.c,v 1.1.1.1 2000/05/17 11:08:41 idiscovery Exp $	*/
3 
4 /*
5  * tixFormMisc.c --
6  *
7  *	Implements the tixForm geometry manager, which has similar
8  *	capability as the Motif Form geometry manager. Please
9  *	refer to the documentation for the use of tixForm.
10  *
11  * Copyright (c) 1996, Expert Interface Technologies
12  *
13  * See the file "license.terms" for information on usage and redistribution
14  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15  *
16  */
17 
18 #include "tixPort.h"
19 #include "tix.h"
20 #include "tixForm.h"
21 
22 /*
23  * SubCommands of the tixForm command.
24  */
25 TIX_DECLARE_SUBCMD(TixFm_Info);
26 
27 static void 		AttachInfo _ANSI_ARGS_((Tcl_Interp * interp,
28 			    FormInfo * clientPtr, int axis, int which));
29 static int		ConfigureAttachment _ANSI_ARGS_((FormInfo *clientPtr,
30 			    Tk_Window topLevel, Tcl_Interp* interp,
31 			    int axis, int which, Tcl_Obj * value));
32 static int		ConfigureFill _ANSI_ARGS_((
33 			    FormInfo *clientPtr, Tk_Window tkwin,
34 			    Tcl_Interp* interp, char *value));
35 static int		ConfigurePadding _ANSI_ARGS_((
36 			    FormInfo *clientPtr, Tk_Window tkwin,
37 			    Tcl_Interp* interp, int axis, int which,
38 			    char *value));
39 static int		ConfigureSpring _ANSI_ARGS_((FormInfo *clientPtr,
40 			    Tk_Window topLevel, Tcl_Interp* interp,
41 			    int axis, int which, Tcl_Obj * value));
42 
43 
44 /*----------------------------------------------------------------------
45  * TixFm_Info --
46  *
47  *	Return the information about the attachment of a client window
48  *----------------------------------------------------------------------
49  */
TixFm_Info(clientData,interp,argc,argv)50 int TixFm_Info(clientData, interp, argc, argv)
51     ClientData clientData;	/* Main window associated with
52 				 * interpreter. */
53     Tcl_Interp *interp;		/* Current interpreter. */
54     int argc;			/* Number of arguments. */
55     char **argv;		/* Argument strings. */
56 {
57     Tk_Window topLevel = (Tk_Window) clientData;
58     FormInfo * clientPtr;
59     char buff[256];
60     int i,j;
61     static char *sideNames[2][2] = {
62 	{"-left", "-right"},
63 	{"-top", "-bottom"}
64     };
65     static char *padNames[2][2] = {
66 	{"-padleft", "-padright"},
67 	{"-padtop", "-padbottom"}
68     };
69 
70     clientPtr = TixFm_FindClientPtrByName(interp, argv[0], topLevel);
71     if (clientPtr == NULL) {
72 	return TCL_ERROR;
73     }
74 
75     if (argc == 2) {
76 	/* user wants some specific info
77 	 */
78 
79 	for (i=0; i<2; i++) {
80 	    for (j=0; j<2; j++) {
81 		/* Do you want to know attachment? */
82 		if (strcmp(argv[1], sideNames[i][j]) == 0) {
83 		    AttachInfo(interp, clientPtr, i, j);
84 		    return TCL_OK;
85 		}
86 
87 		/* Do you want to know padding? */
88 		if (strcmp(argv[1], padNames[i][j]) == 0) {
89 		    Tcl_SetIntObj(Tcl_GetObjResult(interp),clientPtr->pad[i][j]);
90 		    return TCL_OK;
91 		}
92 	    }
93 	}
94 	Tcl_AppendResult(interp, "Unknown option \"", argv[1], "\"", NULL);
95 	return TCL_ERROR;
96     }
97 
98     /* Otherwise, give full info */
99 
100     for (i=0; i<2; i++) {
101 	for (j=0; j<2; j++) {
102 	    /* The information about attachment */
103 	    Tcl_AppendElement(interp,sideNames[i][j]);
104 	    AttachInfo(interp, clientPtr, i, j);
105 
106 	    /* The information about padding */
107 	    Tcl_AppendElement(interp, padNames[i][j]);
108 	    sprintf(buff, "%d", clientPtr->pad[i][j]);
109 	    Tcl_IntResults(interp, 1, 1, clientPtr->pad[i][j]);
110 	}
111     }
112     return TCL_OK;
113 }
114 
AttachInfo(interp,clientPtr,axis,which)115 static void AttachInfo(interp, clientPtr, axis, which)
116     Tcl_Interp * interp;
117     FormInfo * clientPtr;
118     int axis;
119     int which;
120 {
121     char buff[256];
122 
123     switch(clientPtr->attType[axis][which]) {
124       case ATT_NONE:
125 	Tcl_AppendElement(interp, "none");
126 	break;
127 
128       case ATT_GRID:
129 	sprintf(buff, "{%%%d %d}", clientPtr->att[axis][which].grid,
130 	    clientPtr->off[axis][which]);
131 	Tcl_AppendResult(interp, buff, " ", NULL);
132 	break;
133 
134       case ATT_OPPOSITE:
135 	sprintf(buff, "%d", clientPtr->off[axis][which]);
136 	Tcl_AppendResult(interp, "{",
137 	    Tk_PathName(clientPtr->att[axis][which].widget->tkwin),
138 	    " ", buff, "} ", NULL);
139 	break;
140 
141       case ATT_PARALLEL:
142 	sprintf(buff, "%d", clientPtr->off[axis][which]);
143 	Tcl_AppendResult(interp, "{&",
144 	    Tk_PathName(clientPtr->att[axis][which].widget->tkwin),
145 	    " ", buff, "} ", NULL);
146 	break;
147     }
148 }
149 
150 /*----------------------------------------------------------------------
151  * Form Parameter Configuration
152  *
153  *----------------------------------------------------------------------
154  */
ConfigureAttachment(clientPtr,topLevel,interp,axis,which,avalue)155 static int ConfigureAttachment(clientPtr, topLevel, interp, axis, which, avalue)
156     FormInfo *clientPtr;
157     Tk_Window topLevel;
158     Tcl_Interp* interp;
159     int axis, which;
160     Tcl_Obj * avalue;
161 {
162     char *value = Tcl_GetString(avalue);
163     Tk_Window tkwin;
164     FormInfo * attWidget;
165     int code = TCL_OK;
166     int offset;
167     int grid;
168     int argc;
169     Tcl_Obj **objv;
170     int delta = 0;
171 
172     if (Tcl_ListObjGetElements(interp, avalue, &argc, &objv) != TCL_OK) {
173 	return TCL_ERROR;
174     }
175 
176     switch (argv[0][0]) {
177       case '#':		/* Attached to grid */
178       case '%': 	/* Attached to percent (aka grid) */
179 	{Tcl_Obj *temp = Tcl_NewStringObj(Tcl_GetString(objv[0])+1,-1);
180 	 if (Tcl_GetIntFromObj(interp,temp,&grid) != TCL_OK) {
181 	    Tcl_DecrRefCount(temp);
182 	    goto error;
183 	 }
184 	clientPtr->attType[axis][which]   = ATT_GRID;
185 	clientPtr->att[axis][which].grid  = grid;
186 	Tcl_DecrRefCount(temp);
187 	}
188 	break;
189 
190       case '&': 		/* Attached to parallel widget */
191 	if (argc < 2)
192 	   goto malformed;
193 	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[++delta]), topLevel);
194 
195 	if (tkwin != NULL) {
196 	    if (Tk_IsTopLevel(tkwin)) {
197 		Tcl_AppendResult(interp, "can't attach to \"", Tcl_GetString(objv[1]),
198 	    	    "\": it's a top-level window", (char *) NULL);
199 		goto error;
200 	    }
201 	    attWidget = TixFm_GetFormInfo(tkwin, 1);
202 	    TixFm_AddToMaster(clientPtr->master, attWidget);
203 
204 	    clientPtr->attType[axis][which]    = ATT_PARALLEL;
205 	    clientPtr->att[axis][which].widget = attWidget;
206 	} else {
207 	    goto error;
208 	}
209 	break;
210 
211       case '.': 		/* Attach to opposite widget */
212 	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[0]), topLevel);
213 
214 	if (tkwin != NULL) {
215 	    if (Tk_IsTopLevel(tkwin)) {
216 		Tcl_AppendResult(interp, "can't attach to \"", value,
217 	    	    "\": it's a top-level window", (char *) NULL);
218 		goto error;
219 	    }
220 	    attWidget = TixFm_GetFormInfo(tkwin, 1);
221 	    TixFm_AddToMaster(clientPtr->master, attWidget);
222 
223 	    clientPtr->attType[axis][which]    = ATT_OPPOSITE;
224 	    clientPtr->att[axis][which].widget = attWidget;
225 	} else {
226 	    goto error;
227 	}
228 	break;
229 
230       case 'n':		/* none */
231 	if (argc == 1 && strcmp(argv[0], "none") == 0) {
232 	    clientPtr->attType[axis][which]    = ATT_NONE;
233 	    goto done;
234 	} else {
235 	    goto malformed;
236 	}
237 	break;
238 
239       default:		/* Check if is attached to pixel */
240 	/* If there is only one value, this can be the offset with implicit
241 	 * anchor point 0% or max_grid%
242 	 */
243 	if (argc != 1) {
244 	    goto malformed;
245 	}
246 	if (Tk_GetPixels(interp, topLevel, argv[0], &offset) != TCL_OK) {
247 	    goto error;
248 	}
249 
250 	clientPtr->attType[axis][which]      = ATT_GRID;
251 	clientPtr->off    [axis][which]      = offset;
252 	if (offset < 0 || (offset == 0 && strcmp(argv[0], "-0") ==0)) {
253 	    clientPtr->att[axis][which].grid = clientPtr->master->grids[axis];
254 	} else {
255 	    clientPtr->att[axis][which].grid = 0;
256 	}
257 
258 	goto done;	/* We have already gotten both anchor and offset */
259     }
260 
261     if (argc  == 2+delta) {
262 	if (Tk_GetPixels(interp, topLevel, argv[1+delta], &offset) != TCL_OK) {
263 	    goto error;
264 	}
265     	clientPtr->off[axis][which] = offset;
266     } else {
267 	clientPtr->off[axis][which] = 0;
268 	if (argc != 1+delta) {
269      malformed:
270 	    Tcl_AppendResult(interp, "Malformed attachment value \"", value,
271 		"\"", NULL);
272      error:
273 	    code = TCL_ERROR;
274 	    goto done;
275 	}
276     }
277 
278   done:
279     if (code == TCL_ERROR) {
280 	clientPtr->attType[axis][which] = ATT_NONE;
281 	clientPtr->off[axis][which] = 0;
282     }
283     return code;
284 }
285 
ConfigurePadding(clientPtr,tkwin,interp,axis,which,value)286 static int ConfigurePadding(clientPtr, tkwin, interp, axis, which, value)
287     FormInfo *clientPtr;
288     Tk_Window tkwin;
289     Tcl_Interp* interp;
290     int axis, which;
291     char *value;
292 {
293     int p_value;
294 
295     if (Tk_GetPixels(interp, tkwin, value, &p_value) != TCL_OK) {
296 	return TCL_ERROR;
297     }
298     else {
299 	clientPtr->pad[axis][which] = p_value;
300 	return TCL_OK;
301     }
302 }
303 
ConfigureFill(clientPtr,tkwin,interp,value)304 static int ConfigureFill(clientPtr, tkwin, interp, value)
305     FormInfo *clientPtr;
306     Tk_Window tkwin;
307     Tcl_Interp* interp;
308     char *value;
309 {
310     size_t len = strlen(value);
311 
312     if (strncmp(value, "x", len) == 0) {
313 	clientPtr->fill[AXIS_X] = 1;
314 	clientPtr->fill[AXIS_Y] = 0;
315     }
316     else if (strncmp(value, "y", len) == 0) {
317 	clientPtr->fill[AXIS_X] = 0;
318 	clientPtr->fill[AXIS_Y] = 1;
319     }
320     else if (strncmp(value, "both", len) == 0) {
321 	clientPtr->fill[AXIS_X] = 1;
322 	clientPtr->fill[AXIS_Y] = 1;
323     }
324     else if (strncmp(value, "none", len) == 0) {
325 	clientPtr->fill[AXIS_X] = 0;
326 	clientPtr->fill[AXIS_Y] = 0;
327     }
328     else {
329 	Tcl_AppendResult(interp, "bad fill style \"", value,
330 	    "\": must be none, x, y, or both", NULL);
331 	return TCL_ERROR;
332     }
333 
334     return TCL_OK;
335 }
336 
ConfigureSpring(clientPtr,topLevel,interp,axis,which,value)337 static int ConfigureSpring(clientPtr, topLevel, interp, axis, which, value)
338     FormInfo *clientPtr;
339     Tk_Window topLevel;
340     Tcl_Interp* interp;
341     int axis, which;
342     Tcl_Obj * value;
343 {
344     int         strength;
345     int		i = axis, j = which;
346 
347     if (Tcl_GetIntFromObj(interp, value, &strength) != TCL_OK) {
348 	return TCL_ERROR;
349     }
350 
351     clientPtr->spring[i][j] = strength;
352 
353     if (clientPtr->attType[i][j] == ATT_OPPOSITE) {
354 	FormInfo * oppo;
355 
356 	oppo = clientPtr->att[i][j].widget;
357 	oppo->spring[i][!j]  = strength;
358 
359 	if (strength != 0 && clientPtr->strWidget[i][j] == NULL) {
360 	    clientPtr->strWidget[i][j] = oppo;
361 
362 	    if (oppo->strWidget[i][!j] != clientPtr) {
363 		if (oppo->strWidget[i][!j] != NULL) {
364 		    oppo->strWidget[i][!j]->strWidget[i][j] = NULL;
365 		    oppo->strWidget[i][!j]->spring[i][j]  = 0;
366 		}
367 	    }
368 	    oppo->strWidget[i][!j] = clientPtr;
369 	}
370     }
371 
372     return TCL_OK;
373 }
374 
TixFm_Configure(clientPtr,topLevel,interp,argc,argv)375 int TixFm_Configure(clientPtr, topLevel, interp, argc, argv)
376     FormInfo *clientPtr;
377     Tk_Window topLevel;
378     Tcl_Interp* interp;
379     int argc;
380     char **argv;
381 {
382     int i, flag, value;
383 
384     for (i=0; i< argc; i+=2) {
385 	flag  = i;
386 	value = i+1;
387 
388 	if (strcmp(argv[flag], "-in") == 0) {
389 	    /* Reset the parent of the widget
390 	     */
391 	    Tcl_AppendResult(interp,
392 		"\"-in \" must be the first option given to tixForm", NULL);
393 	    return TCL_ERROR;
394 	} else if (strcmp(argv[flag], "-l") == 0) {
395 	    if (ConfigureAttachment(clientPtr, topLevel, interp,
396 		0, 0, objv[value]) == TCL_ERROR) {
397 
398 		return TCL_ERROR;
399 	    }
400 	} else if (strcmp(argv[flag], "-left") == 0) {
401 	    if (ConfigureAttachment(clientPtr, topLevel, interp,
402 		0, 0, objv[value]) == TCL_ERROR) {
403 
404 		return TCL_ERROR;
405 	    }
406 	} else if (strcmp(argv[flag], "-r") == 0) {
407 	    if (ConfigureAttachment(clientPtr, topLevel, interp,
408 		0, 1, objv[value]) == TCL_ERROR) {
409 
410 		return TCL_ERROR;
411 	    }
412 	} else if (strcmp(argv[flag], "-right") == 0) {
413 	    if (ConfigureAttachment(clientPtr, topLevel, interp,
414 		0, 1, objv[value]) == TCL_ERROR) {
415 
416 		return TCL_ERROR;
417 	    }
418 	} else if (strcmp(argv[flag], "-top") == 0) {
419 	    if (ConfigureAttachment(clientPtr, topLevel, interp,
420 	        1, 0, objv[value]) == TCL_ERROR) {
421 
422 		return TCL_ERROR;
423 	    }
424 	} else if (strcmp(argv[flag], "-t") == 0) {
425 	    if (ConfigureAttachment(clientPtr, topLevel, interp,
426 	        1, 0, objv[value]) == TCL_ERROR) {
427 
428 		return TCL_ERROR;
429 	    }
430 	} else if (strcmp(argv[flag], "-bottom") == 0) {
431 	    if (ConfigureAttachment(clientPtr, topLevel, interp,
432 		1, 1, objv[value]) == TCL_ERROR) {
433 
434 		return TCL_ERROR;
435 	    }
436 	} else if (strcmp(argv[flag], "-b") == 0) {
437 	    if (ConfigureAttachment(clientPtr, topLevel, interp,
438 		1, 1, objv[value]) == TCL_ERROR) {
439 
440 		return TCL_ERROR;
441 	    }
442 	} else if (strcmp(argv[flag], "-padx") == 0) {
443 	    if (ConfigurePadding(clientPtr, topLevel, interp,
444   	        0, 0, argv[value]) == TCL_ERROR) {
445 
446 		return TCL_ERROR;
447 	    }
448 	    if (ConfigurePadding(clientPtr, topLevel, interp,
449 		0, 1, argv[value]) == TCL_ERROR) {
450 
451 		return TCL_ERROR;
452 	    }
453 	} else if (strcmp(argv[flag], "-pady") == 0) {
454 	    if (ConfigurePadding(clientPtr,topLevel,interp,
455 		1, 0, argv[value]) == TCL_ERROR) {
456 
457 		return TCL_ERROR;
458 	    }
459 	    if (ConfigurePadding(clientPtr, topLevel, interp,
460 		1, 1, argv[value]) == TCL_ERROR) {
461 
462 		return TCL_ERROR;
463 	    }
464 	} else if (strcmp(argv[flag], "-padleft") == 0) {
465 	    if (ConfigurePadding(clientPtr, topLevel, interp,
466 		0, 0, argv[value]) == TCL_ERROR) {
467 
468 		return TCL_ERROR;
469 	    }
470 	} else if (strcmp(argv[flag], "-lp") == 0) {
471 	    if (ConfigurePadding(clientPtr, topLevel, interp,
472 		0, 0, argv[value]) == TCL_ERROR) {
473 
474 		return TCL_ERROR;
475 	    }
476 	} else if (strcmp(argv[flag], "-padright")== 0){
477 	    if (ConfigurePadding(clientPtr, topLevel, interp,
478 		0, 1, argv[value]) == TCL_ERROR) {
479 
480 		return TCL_ERROR;
481 	    }
482 	} else if (strcmp(argv[flag], "-rp")== 0){
483 	    if (ConfigurePadding(clientPtr, topLevel, interp,
484 		0, 1, argv[value]) == TCL_ERROR) {
485 
486 		return TCL_ERROR;
487 	    }
488 	} else if (strcmp(argv[flag], "-padtop")== 0) {
489 	    if (ConfigurePadding(clientPtr, topLevel, interp,
490 		1, 0, argv[value]) == TCL_ERROR) {
491 
492 		return TCL_ERROR;
493 	    }
494 	} else if (strcmp(argv[flag], "-tp")== 0) {
495 	    if (ConfigurePadding(clientPtr, topLevel, interp,
496 		1, 0, argv[value]) == TCL_ERROR) {
497 
498 		return TCL_ERROR;
499 	    }
500 	} else if (strcmp(argv[flag],"-padbottom")== 0){
501 	    if (ConfigurePadding(clientPtr, topLevel, interp,
502 		1, 1, argv[value]) == TCL_ERROR) {
503 
504 		return TCL_ERROR;
505 	    }
506 	} else if (strcmp(argv[flag],"-bp")== 0){
507 	    if (ConfigurePadding(clientPtr, topLevel, interp,
508 		1, 1, argv[value]) == TCL_ERROR) {
509 
510 		return TCL_ERROR;
511 	    }
512 	} else if (strcmp(argv[flag], "-leftspring") == 0) {
513 	    if (ConfigureSpring(clientPtr, topLevel, interp,
514 		0, 0, objv[value]) == TCL_ERROR) {
515 		return TCL_ERROR;
516 	    }
517 	} else if (strcmp(argv[flag], "-ls") == 0) {
518 	    if (ConfigureSpring(clientPtr, topLevel, interp,
519 		0, 0, objv[value]) == TCL_ERROR) {
520 		return TCL_ERROR;
521 	    }
522 	} else if (strcmp(argv[flag], "-rightspring") == 0) {
523 	    if (ConfigureSpring(clientPtr, topLevel, interp,
524 		0, 1, objv[value]) == TCL_ERROR) {
525 		return TCL_ERROR;
526 	    }
527 	} else if (strcmp(argv[flag], "-rs") == 0) {
528 	    if (ConfigureSpring(clientPtr, topLevel, interp,
529 		0, 1, objv[value]) == TCL_ERROR) {
530 		return TCL_ERROR;
531 	    }
532 	} else if (strcmp(argv[flag], "-topspring") == 0) {
533 	    if (ConfigureSpring(clientPtr, topLevel, interp,
534 		1, 0, objv[value]) == TCL_ERROR) {
535 		return TCL_ERROR;
536 	    }
537 	} else if (strcmp(argv[flag], "-ts") == 0) {
538 	    if (ConfigureSpring(clientPtr, topLevel, interp,
539 		1, 0, objv[value]) == TCL_ERROR) {
540 		return TCL_ERROR;
541 	    }
542 	} else if (strcmp(argv[flag], "-bottomspring") == 0) {
543 	    if (ConfigureSpring(clientPtr, topLevel, interp,
544 		1, 1, objv[value]) == TCL_ERROR) {
545 		return TCL_ERROR;
546 	    }
547 	} else if (strcmp(argv[flag], "-bs") == 0) {
548 	    if (ConfigureSpring(clientPtr, topLevel, interp,
549 		1, 1, objv[value]) == TCL_ERROR) {
550 		return TCL_ERROR;
551 	    }
552 	} else if (strcmp(argv[flag], "-fill") == 0) {
553 	    if (ConfigureFill(clientPtr, topLevel, interp,
554 		argv[value]) == TCL_ERROR) {
555 		return TCL_ERROR;
556 	    }
557 	} else {
558 	    Tcl_AppendResult(interp, "Wrong option \"",
559 		argv[i], "\".", (char *) NULL);
560 	    return TCL_ERROR;
561 	}
562     }
563 
564     /*
565      * Clear the previously set default attachment if the opposide
566      * edge is attached.
567      */
568 
569 #if 0
570     /* (1) The X axis */
571     if ((clientPtr->attType[0][0] ==  ATT_DEFAULT_PIXEL)
572 	&&(clientPtr->attType[0][1]  !=  ATT_NONE)) {
573 	clientPtr->attType[0][0]   = ATT_NONE;
574     }
575 
576     /* (2) The Y axis */
577     if ((clientPtr->attType[1][0] ==  ATT_DEFAULT_PIXEL)
578 	&&(clientPtr->attType[1][1]  !=  ATT_NONE)) {
579 	clientPtr->attType[1][0]   = ATT_NONE;
580     }
581 #endif
582 
583     return TCL_OK;
584 }
585 
586