2 static char Xrcsid
[] = "$XConsortium: Form.c,v 1.34 89/12/13 13:51:07 kit Exp $";
6 /***********************************************************
7 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
8 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the names of Digital or MIT not be
17 used in advertising or publicity pertaining to distribution of the
18 software without specific, written prior permission.
20 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28 ******************************************************************/
30 #include <X11/IntrinsicP.h>
31 #include <X11/StringDefs.h>
32 #include <X11/Xmu/Converters.h>
33 #include <X11/Xmu/CharSet.h>
34 #include <./Xaw3_1XawInit.h>
35 #include <./Xaw3_1FormP.h>
37 /* Private Definitions */
39 static int default_value
= -99999;
41 #define Offset(field) XtOffset(FormWidget, form.field)
42 static XtResource resources
[] = {
43 {XtNdefaultDistance
, XtCThickness
, XtRInt
, sizeof(int),
44 Offset(default_spacing
), XtRImmediate
, (caddr_t
)4}
48 static XtEdgeType defEdge
= XtRubber
;
50 #define Offset(field) XtOffset(FormConstraints, form.field)
51 static XtResource formConstraintResources
[] = {
52 {XtNtop
, XtCEdge
, XtREdgeType
, sizeof(XtEdgeType
),
53 Offset(top
), XtREdgeType
, (XtPointer
)&defEdge
},
54 {XtNbottom
, XtCEdge
, XtREdgeType
, sizeof(XtEdgeType
),
55 Offset(bottom
), XtREdgeType
, (XtPointer
)&defEdge
},
56 {XtNleft
, XtCEdge
, XtREdgeType
, sizeof(XtEdgeType
),
57 Offset(left
), XtREdgeType
, (XtPointer
)&defEdge
},
58 {XtNright
, XtCEdge
, XtREdgeType
, sizeof(XtEdgeType
),
59 Offset(right
), XtREdgeType
, (XtPointer
)&defEdge
},
60 {XtNhorizDistance
, XtCThickness
, XtRInt
, sizeof(int),
61 Offset(dx
), XtRInt
, (XtPointer
) &default_value
},
62 {XtNfromHoriz
, XtCWidget
, XtRWidget
, sizeof(Widget
),
63 Offset(horiz_base
), XtRWidget
, (XtPointer
)NULL
},
64 {XtNvertDistance
, XtCThickness
, XtRInt
, sizeof(int),
65 Offset(dy
), XtRInt
, (XtPointer
) &default_value
},
66 {XtNfromVert
, XtCWidget
, XtRWidget
, sizeof(Widget
),
67 Offset(vert_base
), XtRWidget
, (XtPointer
)NULL
},
68 {XtNresizable
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
69 Offset(allow_resize
), XtRImmediate
, (XtPointer
) FALSE
},
73 static void ClassInitialize(), ClassPartInitialize(), Initialize(), Resize();
74 static void ConstraintInitialize();
75 static Boolean
SetValues(), ConstraintSetValues();
76 static XtGeometryResult
GeometryManager(), PreferredGeometry();
77 static void ChangeManaged();
78 static Boolean
Layout();
80 FormClassRec formClassRec
= {
81 { /* core_class fields */
82 /* superclass */ (WidgetClass
) &constraintClassRec
,
83 /* class_name */ "Form",
84 /* widget_size */ sizeof(FormRec
),
85 /* class_initialize */ ClassInitialize
,
86 /* class_part_init */ ClassPartInitialize
,
87 /* class_inited */ FALSE
,
88 /* initialize */ Initialize
,
89 /* initialize_hook */ NULL
,
90 /* realize */ XtInheritRealize
,
93 /* resources */ resources
,
94 /* num_resources */ XtNumber(resources
),
95 /* xrm_class */ NULLQUARK
,
96 /* compress_motion */ TRUE
,
97 /* compress_exposure */ TRUE
,
98 /* compress_enterleave*/ TRUE
,
99 /* visible_interest */ FALSE
,
102 /* expose */ XtInheritExpose
,
103 /* set_values */ SetValues
,
104 /* set_values_hook */ NULL
,
105 /* set_values_almost */ XtInheritSetValuesAlmost
,
106 /* get_values_hook */ NULL
,
107 /* accept_focus */ NULL
,
108 /* version */ XtVersion
,
109 /* callback_private */ NULL
,
111 /* query_geometry */ PreferredGeometry
,
112 /* display_accelerator*/ XtInheritDisplayAccelerator
,
115 { /* composite_class fields */
116 /* geometry_manager */ GeometryManager
,
117 /* change_managed */ ChangeManaged
,
118 /* insert_child */ XtInheritInsertChild
,
119 /* delete_child */ XtInheritDeleteChild
,
122 { /* constraint_class fields */
123 /* subresourses */ formConstraintResources
,
124 /* subresource_count */ XtNumber(formConstraintResources
),
125 /* constraint_size */ sizeof(FormConstraintsRec
),
126 /* initialize */ ConstraintInitialize
,
128 /* set_values */ ConstraintSetValues
,
131 { /* form_class fields */
136 WidgetClass formWidgetClass
= (WidgetClass
)&formClassRec
;
138 /****************************************************************
142 ****************************************************************/
145 static XrmQuark XtQChainLeft
, XtQChainRight
, XtQChainTop
,
146 XtQChainBottom
, XtQRubber
;
148 #define done(address, type) \
149 { toVal->size = sizeof(type); \
150 toVal->addr = (caddr_t) address; \
155 static void _CvtStringToEdgeType(args
, num_args
, fromVal
, toVal
)
156 XrmValuePtr args
; /* unused */
157 Cardinal
*num_args
; /* unused */
161 static XtEdgeType edgeType
;
163 char lowerName
[1000];
165 XmuCopyISOLatin1Lowered (lowerName
, (char*)fromVal
->addr
);
166 q
= XrmStringToQuark(lowerName
);
167 if (q
== XtQChainLeft
) {
168 edgeType
= XtChainLeft
;
169 done(&edgeType
, XtEdgeType
);
171 if (q
== XtQChainRight
) {
172 edgeType
= XtChainRight
;
173 done(&edgeType
, XtEdgeType
);
175 if (q
== XtQChainTop
) {
176 edgeType
= XtChainTop
;
177 done(&edgeType
, XtEdgeType
);
179 if (q
== XtQChainBottom
) {
180 edgeType
= XtChainBottom
;
181 done(&edgeType
, XtEdgeType
);
183 if (q
== XtQRubber
) {
185 done(&edgeType
, XtEdgeType
);
187 XtStringConversionWarning(fromVal
->addr
, "edgeType");
192 static void ClassInitialize()
194 static XtConvertArgRec parentCvtArgs
[] = {
195 {XtBaseOffset
, (caddr_t
)XtOffset(Widget
, core
.parent
), sizeof(Widget
)}
197 XawInitializeWidgetSet();
198 XtQChainLeft
= XrmStringToQuark("chainleft");
199 XtQChainRight
= XrmStringToQuark("chainright");
200 XtQChainTop
= XrmStringToQuark("chaintop");
201 XtQChainBottom
= XrmStringToQuark("chainbottom");
202 XtQRubber
= XrmStringToQuark("rubber");
204 XtAddConverter( XtRString
, XtREdgeType
, _CvtStringToEdgeType
, NULL
, 0 );
205 XtAddConverter( XtRString
, XtRWidget
, XmuCvtStringToWidget
,
206 parentCvtArgs
, XtNumber(parentCvtArgs
) );
209 static void ClassPartInitialize(class)
212 register FormWidgetClass c
= (FormWidgetClass
)class;
214 if (c
->form_class
.layout
== XtInheritLayout
)
215 c
->form_class
.layout
= Layout
;
220 static void Initialize(request
, new)
223 FormWidget fw
= (FormWidget
)new;
225 fw
->form
.old_width
= fw
->core
.width
;
226 fw
->form
.old_height
= fw
->core
.height
;
227 fw
->form
.no_refigure
= False
;
228 fw
->form
.needs_relayout
= False
;
229 fw
->form
.resize_in_layout
= True
;
233 static void RefigureLocations(w
)
236 if (w
->form
.no_refigure
) {
237 w
->form
.needs_relayout
= True
;
240 (*((FormWidgetClass
)w
->core
.widget_class
)->form_class
.layout
)
241 ( w
, w
->core
.width
, w
->core
.height
);
242 w
->form
.needs_relayout
= False
;
246 static void LayoutChild(w
)
249 FormConstraints form
= (FormConstraints
)w
->core
.constraints
;
253 switch (form
->form
.layout_state
) {
256 form
->form
.layout_state
= LayoutInProgress
;
262 case LayoutInProgress
:
265 Cardinal num_subs
= 2;
266 subs
[0] = w
->core
.name
;
267 subs
[1] = w
->core
.parent
->core
.name
;
268 XtAppWarningMsg(XtWidgetToApplicationContext(w
),
269 "constraintLoop","xawFormLayout","XawToolkitError",
270 "constraint loop detected while laying out child '%s' in FormWidget '%s'",
277 if ((ref
= form
->form
.horiz_base
) != (Widget
)NULL
) {
279 x
+= ref
->core
.x
+ ref
->core
.width
+ (ref
->core
.border_width
<< 1);
281 if ((ref
= form
->form
.vert_base
) != (Widget
)NULL
) {
283 y
+= ref
->core
.y
+ ref
->core
.height
+ (ref
->core
.border_width
<< 1);
285 XtMoveWidget( w
, x
, y
);
286 form
->form
.layout_state
= LayoutDone
;
291 static Boolean
Layout(fw
, width
, height
)
293 Dimension width
, height
;
295 int num_children
= fw
->composite
.num_children
;
296 WidgetList children
= fw
->composite
.children
;
301 for (childP
= children
; childP
- children
< num_children
; childP
++) {
302 FormConstraints form
= (FormConstraints
)(*childP
)->core
.constraints
;
303 form
->form
.layout_state
= LayoutPending
;
307 for (childP
= children
; childP
- children
< num_children
; childP
++) {
308 if (XtIsManaged(*childP
)) {
310 LayoutChild(*childP
);
311 x
= (*childP
)->core
.x
+ (*childP
)->core
.width
312 + ((*childP
)->core
.border_width
<< 1);
313 y
= (*childP
)->core
.y
+ (*childP
)->core
.height
314 + ((*childP
)->core
.border_width
<< 1);
315 if (maxx
< x
) maxx
= x
;
316 if (maxy
< y
) maxy
= y
;
320 fw
->form
.preferred_width
= (maxx
+= fw
->form
.default_spacing
);
321 fw
->form
.preferred_height
= (maxy
+= fw
->form
.default_spacing
);
323 if (fw
->form
.resize_in_layout
324 && (maxx
!= fw
->core
.width
|| maxy
!= fw
->core
.height
)) {
325 XtGeometryResult result
;
326 result
= XtMakeResizeRequest((Widget
)fw
,
327 (Dimension
)maxx
, (Dimension
)maxy
,
328 (Dimension
*)&maxx
, (Dimension
*)&maxy
);
329 if (result
== XtGeometryAlmost
)
330 result
= XtMakeResizeRequest((Widget
)fw
,
331 (Dimension
)maxx
, (Dimension
)maxy
,
333 fw
->form
.old_width
= fw
->core
.width
;
334 fw
->form
.old_height
= fw
->core
.height
;
335 ret_val
= (result
== XtGeometryYes
);
336 } else ret_val
= False
;
342 static Position
TransformCoord(loc
, old
, new, type
)
343 register Position loc
;
347 if (type
== XtRubber
) {
348 if ( ((int) old
) > 0)
349 loc
= (loc
* new) / old
;
351 else if (type
== XtChainBottom
|| type
== XtChainRight
)
352 loc
+= (Position
)new - (Position
)old
;
354 /* I don't see any problem with returning values less than zero. */
360 static void Resize(w
)
363 FormWidget fw
= (FormWidget
)w
;
364 WidgetList children
= fw
->composite
.children
;
365 int num_children
= fw
->composite
.num_children
;
368 Dimension width
, height
;
370 for (childP
= children
; childP
- children
< num_children
; childP
++) {
371 FormConstraints form
= (FormConstraints
)(*childP
)->core
.constraints
;
372 if (!XtIsManaged(*childP
)) continue;
373 x
= TransformCoord( (*childP
)->core
.x
, fw
->form
.old_width
,
374 fw
->core
.width
, form
->form
.left
);
375 y
= TransformCoord( (*childP
)->core
.y
, fw
->form
.old_height
,
376 fw
->core
.height
, form
->form
.top
);
378 form
->form
.virtual_width
=
379 TransformCoord((Position
)((*childP
)->core
.x
380 + form
->form
.virtual_width
381 + 2 * (*childP
)->core
.border_width
),
382 fw
->form
.old_width
, fw
->core
.width
,
384 - (x
+ 2 * (*childP
)->core
.border_width
);
386 form
->form
.virtual_height
=
387 TransformCoord((Position
)((*childP
)->core
.y
388 + form
->form
.virtual_height
389 + 2 * (*childP
)->core
.border_width
),
390 fw
->form
.old_height
, fw
->core
.height
,
392 - ( y
+ 2 * (*childP
)->core
.border_width
);
395 (form
->form
.virtual_width
< 1) ? 1 : form
->form
.virtual_width
;
397 (form
->form
.virtual_height
< 1) ? 1 : form
->form
.virtual_height
;
399 XtConfigureWidget( *childP
, x
, y
, (Dimension
)width
, (Dimension
)height
,
400 (*childP
)->core
.border_width
);
403 fw
->form
.old_width
= fw
->core
.width
;
404 fw
->form
.old_height
= fw
->core
.height
;
409 static XtGeometryResult
GeometryManager(w
, request
, reply
)
411 XtWidgetGeometry
*request
;
412 XtWidgetGeometry
*reply
; /* RETURN */
414 FormConstraints form
= (FormConstraints
)w
->core
.constraints
;
415 XtWidgetGeometry allowed
;
417 if ((request
->request_mode
& ~(XtCWQueryOnly
| CWWidth
| CWHeight
)) ||
418 !form
->form
.allow_resize
)
421 if (request
->request_mode
& CWWidth
)
422 allowed
.width
= request
->width
;
424 allowed
.width
= w
->core
.width
;
426 if (request
->request_mode
& CWHeight
)
427 allowed
.height
= request
->height
;
429 allowed
.height
= w
->core
.height
;
431 if (allowed
.width
== w
->core
.width
&& allowed
.height
== w
->core
.height
)
434 if (!(request
->request_mode
& XtCWQueryOnly
)) {
435 /* reset virtual width and height. */
436 form
->form
.virtual_width
= w
->core
.width
= allowed
.width
;
437 form
->form
.virtual_height
= w
->core
.height
= allowed
.height
;
438 RefigureLocations( (FormWidget
)w
->core
.parent
);
440 return XtGeometryYes
;
446 static Boolean
SetValues(current
, request
, new)
447 Widget current
, request
, new;
454 static void ConstraintInitialize(request
, new)
457 FormConstraints form
= (FormConstraints
)new->core
.constraints
;
458 FormWidget fw
= (FormWidget
)new->core
.parent
;
460 form
->form
.virtual_width
= (int) new->core
.width
;
461 form
->form
.virtual_height
= (int) new->core
.height
;
463 if (form
->form
.dx
== default_value
)
464 form
->form
.dx
= fw
->form
.default_spacing
;
466 if (form
->form
.dy
== default_value
)
467 form
->form
.dy
= fw
->form
.default_spacing
;
471 static Boolean
ConstraintSetValues(current
, request
, new)
472 Widget current
, request
, new;
477 static void ChangeManaged(w
)
480 FormWidget fw
= (FormWidget
)w
;
481 FormConstraints form
;
482 WidgetList children
, childP
;
483 int num_children
= fw
->composite
.num_children
;
487 * Reset virtual width and height for all children.
490 for (children
= childP
= fw
->composite
.children
;
491 childP
- children
< num_children
; childP
++) {
493 if (XtIsManaged(child
)) {
494 form
= (FormConstraints
)child
->core
.constraints
;
497 * If the size is one (1) then we must not change the virtual sizes, as
498 * they contain useful information. If someone actually wants a widget of
499 * width or height one (1) in a form widget he will lose, can't win them all.
501 * Chris D. Peterson 2/9/89.
505 if ( child
->core
.width
!= 1)
506 form
->form
.virtual_width
= (int) child
->core
.width
;
507 if ( child
->core
.height
!= 1)
508 form
->form
.virtual_height
= (int) child
->core
.height
;
511 RefigureLocations( (FormWidget
)w
);
515 static XtGeometryResult
PreferredGeometry( widget
, request
, reply
)
517 XtWidgetGeometry
*request
, *reply
;
519 FormWidget w
= (FormWidget
)widget
;
521 reply
->width
= w
->form
.preferred_width
;
522 reply
->height
= w
->form
.preferred_height
;
523 reply
->request_mode
= CWWidth
| CWHeight
;
524 if ( request
->request_mode
& (CWWidth
| CWHeight
) ==
525 reply
->request_mode
& CWWidth
| CWHeight
526 && request
->width
== reply
->width
527 && request
->height
== reply
->height
)
528 return XtGeometryYes
;
529 else if (reply
->width
== w
->core
.width
&& reply
->height
== w
->core
.height
)
532 return XtGeometryAlmost
;
536 /**********************************************************************
540 **********************************************************************/
543 * Set or reset figuring (ignored if not realized)
546 void XawFormDoLayout(w
, doit
)
550 register FormWidget fw
= (FormWidget
)w
;
552 fw
->form
.no_refigure
= !doit
;
554 if ( XtIsRealized(w
) && fw
->form
.needs_relayout
)
555 RefigureLocations( fw
);