1 /*********************************************************** 2 3 Copyright 1987, 1988, 1994, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21 Except as contained in this notice, the name of The Open Group shall not be 22 used in advertising or otherwise to promote the sale, use or other dealings 23 in this Software without prior written authorization from The Open Group. 24 25 26 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 27 28 All Rights Reserved 29 30 Permission to use, copy, modify, and distribute this software and its 31 documentation for any purpose and without fee is hereby granted, 32 provided that the above copyright notice appear in all copies and that 33 both that copyright notice and this permission notice appear in 34 supporting documentation, and that the name of Digital not be 35 used in advertising or publicity pertaining to distribution of the 36 software without specific, written prior permission. 37 38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 44 SOFTWARE. 45 46 ******************************************************************/ 47 48 #ifdef HAVE_CONFIG_H 49 #include <config.h> 50 #endif 51 #include <X11/IntrinsicP.h> 52 #include <X11/StringDefs.h> 53 #include <X11/Xmu/CharSet.h> 54 #include <X11/Xmu/Converters.h> 55 #include <X11/Xaw/FormP.h> 56 #include <X11/Xaw/XawInit.h> 57 #include "Private.h" 58 59 /* 60 * Class Methods 61 */ 62 static void XawFormChangeManaged(Widget); 63 static void XawFormClassInitialize(void); 64 static void XawFormClassPartInitialize(WidgetClass); 65 static void XawFormConstraintInitialize(Widget, Widget, ArgList, Cardinal*); 66 static Boolean XawFormConstraintSetValues(Widget, Widget, Widget, 67 ArgList, Cardinal*); 68 static XtGeometryResult XawFormGeometryManager(Widget, XtWidgetGeometry*, 69 XtWidgetGeometry*); 70 static void XawFormInitialize(Widget, Widget, ArgList, Cardinal*); 71 #ifndef OLDXAW 72 static void XawFormRealize(Widget, Mask*, XSetWindowAttributes*); 73 static void XawFormRedisplay(Widget, XEvent*, Region); 74 #endif 75 static XtGeometryResult XawFormQueryGeometry(Widget, XtWidgetGeometry*, 76 XtWidgetGeometry*); 77 static void XawFormResize(Widget); 78 static Boolean XawFormSetValues(Widget, Widget, Widget, ArgList, Cardinal*); 79 static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool); 80 81 /* 82 * Prototypes 83 */ 84 static void _CvtStringToEdgeType(XrmValuePtr, Cardinal*, 85 XrmValuePtr, XrmValuePtr); 86 static Bool ChangeFormGeometry(Widget, Bool, unsigned int, unsigned int, 87 Dimension*, Dimension*); 88 Boolean CvtEdgeTypeToString(Display*, XrmValuePtr, Cardinal*, 89 XrmValuePtr, XrmValuePtr, XtPointer*); 90 static void LayoutChild(Widget); 91 static int TransformCoord(int, unsigned int, unsigned int, XtEdgeType); 92 static void ResizeChildren(Widget); 93 94 /* 95 * Initialization 96 */ 97 #ifndef OLDXAW 98 static XtActionsRec actions[] = { 99 {"set-values", XawSetValuesAction}, 100 {"get-values", XawGetValuesAction}, 101 {"declare", XawDeclareAction}, 102 {"call-proc", XawCallProcAction}, 103 }; 104 #endif 105 106 static XrmQuark QchainLeft, QchainRight, QchainTop, QchainBottom, Qrubber; 107 108 #define default_value -99999 109 #define Offset(field) XtOffsetOf(FormRec, form.field) 110 static XtResource resources[] = { 111 { 112 XtNdefaultDistance, 113 XtCThickness, 114 XtRInt, 115 sizeof(int), 116 Offset(default_spacing), 117 XtRImmediate, 118 (XtPointer)4 119 }, 120 #ifndef OLDXAW 121 { 122 XawNdisplayList, 123 XawCDisplayList, 124 XawRDisplayList, 125 sizeof(XawDisplayList*), 126 Offset(display_list), 127 XtRImmediate, 128 NULL 129 }, 130 #endif 131 }; 132 #undef Offset 133 134 #define defEdge XtRubber 135 136 #define Offset(field) XtOffsetOf(FormConstraintsRec, form.field) 137 static XtResource formConstraintResources[] = { 138 { 139 XtNtop, 140 XtCEdge, 141 XtREdgeType, 142 sizeof(XtEdgeType), 143 Offset(top), 144 XtRImmediate, 145 (XtPointer)defEdge 146 }, 147 { 148 XtNbottom, 149 XtCEdge, 150 XtREdgeType, 151 sizeof(XtEdgeType), 152 Offset(bottom), 153 XtRImmediate, 154 (XtPointer)defEdge 155 }, 156 { 157 XtNleft, 158 XtCEdge, 159 XtREdgeType, 160 sizeof(XtEdgeType), 161 Offset(left), 162 XtRImmediate, 163 (XtPointer)defEdge 164 }, 165 { 166 XtNright, 167 XtCEdge, 168 XtREdgeType, 169 sizeof(XtEdgeType), 170 Offset(right), 171 XtRImmediate, 172 (XtPointer)defEdge 173 }, 174 { 175 XtNhorizDistance, 176 XtCThickness, 177 XtRInt, 178 sizeof(int), 179 Offset(dx), 180 XtRImmediate, 181 (XtPointer)default_value 182 }, 183 { 184 XtNfromHoriz, 185 XtCWidget, 186 XtRWidget, 187 sizeof(Widget), 188 Offset(horiz_base), 189 XtRWidget, 190 NULL 191 }, 192 { 193 XtNvertDistance, 194 XtCThickness, 195 XtRInt, 196 sizeof(int), 197 Offset(dy), 198 XtRImmediate, 199 (XtPointer)default_value 200 }, 201 { 202 XtNfromVert, 203 XtCWidget, 204 XtRWidget, 205 sizeof(Widget), 206 Offset(vert_base), 207 XtRWidget, 208 NULL 209 }, 210 { 211 XtNresizable, 212 XtCBoolean, 213 XtRBoolean, 214 sizeof(Boolean), 215 Offset(allow_resize), 216 XtRImmediate, 217 (XtPointer)False 218 }, 219 }; 220 #undef Offset 221 222 FormClassRec formClassRec = { 223 /* core */ 224 { 225 (WidgetClass)&constraintClassRec, /* superclass */ 226 "Form", /* class_name */ 227 sizeof(FormRec), /* widget_size */ 228 XawFormClassInitialize, /* class_initialize */ 229 XawFormClassPartInitialize, /* class_part_init */ 230 False, /* class_inited */ 231 XawFormInitialize, /* initialize */ 232 NULL, /* initialize_hook */ 233 #ifndef OLDXAW 234 XawFormRealize, /* realize */ 235 actions, /* actions */ 236 XtNumber(actions), /* num_actions */ 237 #else 238 XtInheritRealize, /* realize */ 239 NULL, /* actions */ 240 0, /* num_actions */ 241 #endif 242 resources, /* resources */ 243 XtNumber(resources), /* num_resources */ 244 NULLQUARK, /* xrm_class */ 245 True, /* compress_motion */ 246 True, /* compress_exposure */ 247 True, /* compress_enterleave */ 248 False, /* visible_interest */ 249 NULL, /* destroy */ 250 XawFormResize, /* resize */ 251 #ifndef OLDXAW 252 XawFormRedisplay, /* expose */ 253 #else 254 XtInheritExpose, /* expose */ 255 #endif 256 XawFormSetValues, /* set_values */ 257 NULL, /* set_values_hook */ 258 XtInheritSetValuesAlmost, /* set_values_almost */ 259 NULL, /* get_values_hook */ 260 NULL, /* accept_focus */ 261 XtVersion, /* version */ 262 NULL, /* callback_private */ 263 NULL, /* tm_table */ 264 XawFormQueryGeometry, /* query_geometry */ 265 XtInheritDisplayAccelerator, /* display_accelerator */ 266 NULL, /* extension */ 267 }, 268 /* composite */ 269 { 270 XawFormGeometryManager, /* geometry_manager */ 271 XawFormChangeManaged, /* change_managed */ 272 XtInheritInsertChild, /* insert_child */ 273 XtInheritDeleteChild, /* delete_child */ 274 NULL, /* extension */ 275 }, 276 /* constraint */ 277 { 278 formConstraintResources, /* subresourses */ 279 XtNumber(formConstraintResources), /* subresource_count */ 280 sizeof(FormConstraintsRec), /* constraint_size */ 281 XawFormConstraintInitialize, /* initialize */ 282 NULL, /* destroy */ 283 XawFormConstraintSetValues, /* set_values */ 284 NULL, /* extension */ 285 }, 286 /* form */ 287 { 288 Layout, /* layout */ 289 #ifndef OLDXAW 290 NULL, 291 #endif 292 }, 293 }; 294 295 WidgetClass formWidgetClass = (WidgetClass)&formClassRec; 296 297 /* 298 * Implementation 299 */ 300 #ifndef OLDXAW 301 static void 302 XawFormRealize(Widget w, Mask *mask, XSetWindowAttributes *attr) 303 { 304 (*formWidgetClass->core_class.superclass->core_class.realize)(w, mask, attr); 305 306 if (w->core.background_pixmap > XtUnspecifiedPixmap) { 307 XawPixmap *pixmap = 308 XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w), 309 w->core.colormap, (int)w->core.depth); 310 if (pixmap && pixmap->mask) 311 XawReshapeWidget(w, pixmap); 312 } 313 } 314 315 static void 316 XawFormRedisplay(Widget w, XEvent *event, Region region) 317 { 318 FormWidget xaw = (FormWidget)w; 319 320 if (xaw->form.display_list) 321 XawRunDisplayList(w, xaw->form.display_list, event, region); 322 } 323 #endif 324 325 /*ARGSUSED*/ 326 static void 327 _CvtStringToEdgeType(XrmValuePtr args _X_UNUSED, Cardinal *num_args _X_UNUSED, 328 XrmValuePtr fromVal, XrmValuePtr toVal) 329 { 330 static XtEdgeType edgeType; 331 XrmQuark q; 332 char name[12]; 333 334 XmuNCopyISOLatin1Lowered(name, (char*)fromVal->addr, sizeof(name)); 335 q = XrmStringToQuark(name); 336 337 if (q == QchainLeft) 338 edgeType = XtChainLeft; 339 else if (q == QchainRight) 340 edgeType = XtChainRight; 341 else if (q == QchainTop) 342 edgeType = XtChainTop; 343 else if (q == QchainBottom) 344 edgeType = XtChainBottom; 345 else if (q == Qrubber) 346 edgeType = XtRubber; 347 else { 348 XtStringConversionWarning(fromVal->addr, XtREdgeType); 349 toVal->size = 0; 350 toVal->addr = NULL; 351 return; 352 } 353 354 toVal->size = sizeof(XtEdgeType); 355 toVal->addr = (XPointer)&edgeType; 356 } 357 358 /*ARGSUSED*/ 359 Boolean 360 CvtEdgeTypeToString(Display *dpy, XrmValuePtr args _X_UNUSED, Cardinal *num_args _X_UNUSED, 361 XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data _X_UNUSED) 362 { 363 static String buffer; 364 Cardinal size; 365 366 switch (*(XtEdgeType *)fromVal->addr) { 367 case XtChainLeft: 368 buffer = XtEchainLeft; 369 break; 370 case XtChainRight: 371 buffer = XtEchainRight; 372 break; 373 case XtChainTop: 374 buffer = XtEchainTop; 375 break; 376 case XtChainBottom: 377 buffer = XtEchainBottom; 378 break; 379 case XtRubber: 380 buffer = XtErubber; 381 break; 382 default: 383 XawTypeToStringWarning(dpy, XtREdgeType); 384 toVal->addr = NULL; 385 toVal->size = 0; 386 return (False); 387 } 388 389 size = (Cardinal)strlen(buffer) + 1; 390 if (toVal->addr != NULL) { 391 if (toVal->size < size) { 392 toVal->size = size; 393 return (False); 394 } 395 strcpy((char *)toVal->addr, buffer); 396 } 397 else 398 toVal->addr = (XPointer)buffer; 399 toVal->size = sizeof(String); 400 401 return (True); 402 } 403 404 static void 405 XawFormClassInitialize(void) 406 { 407 static XtConvertArgRec parentCvtArgs[] = { 408 {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent), 409 sizeof(Widget)} 410 }; 411 412 char name[12]; 413 414 XawInitializeWidgetSet(); 415 XmuNCopyISOLatin1Lowered(name, XtEchainLeft, sizeof(name)); 416 QchainLeft = XrmStringToQuark(name); 417 XmuNCopyISOLatin1Lowered(name, XtEchainRight, sizeof(name)); 418 QchainRight = XrmStringToQuark(name); 419 XmuNCopyISOLatin1Lowered(name, XtEchainTop, sizeof(name)); 420 QchainTop = XrmStringToQuark(name); 421 XmuNCopyISOLatin1Lowered(name, XtEchainBottom, sizeof(name)); 422 QchainBottom = XrmStringToQuark(name); 423 XmuNCopyISOLatin1Lowered(name, XtErubber, sizeof(name)); 424 Qrubber = XrmStringToQuark(name); 425 426 XtAddConverter(XtRString, XtREdgeType, _CvtStringToEdgeType, NULL, 0); 427 XtSetTypeConverter(XtREdgeType, XtRString, CvtEdgeTypeToString, 428 NULL, 0, XtCacheNone, NULL); 429 XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget, 430 parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone, 431 NULL); 432 XtSetTypeConverter(XtRWidget, XtRString, XmuCvtWidgetToString, 433 NULL, 0, XtCacheNone, NULL); 434 } 435 436 static void 437 XawFormClassPartInitialize(WidgetClass cclass) 438 { 439 FormWidgetClass c = (FormWidgetClass)cclass; 440 FormWidgetClass super = (FormWidgetClass)c->core_class.superclass; 441 442 if (c->form_class.layout == XtInheritLayout) 443 c->form_class.layout = super->form_class.layout; 444 } 445 446 /*ARGSUSED*/ 447 static void 448 XawFormInitialize(Widget request _X_UNUSED, Widget cnew, 449 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 450 { 451 FormWidget fw = (FormWidget)cnew; 452 453 fw->form.old_width = fw->form.old_height = 0; 454 fw->form.no_refigure = False; 455 fw->form.needs_relayout = False; 456 fw->form.resize_in_layout = True; 457 fw->form.resize_is_no_op = False; 458 } 459 460 /* 461 * Function: 462 * ChangeFormGeometry 463 * 464 * Parameters: 465 * w - Form widget 466 * query_only - is only a query? 467 * width - new width and height 468 * height - "" 469 * ret_width - actual size the form is allowed to resize to (return) 470 * ret_height - "" 471 * 472 * Description: 473 * Ask the parent to change the form widget's geometry. 474 * 475 * Returns: 476 * True of children may always be resized 477 */ 478 static Bool 479 ChangeFormGeometry(Widget w, Bool query_only, 480 unsigned int width, unsigned int height, 481 Dimension *ret_width, Dimension *ret_height) 482 { 483 FormWidget fw = (FormWidget)w; 484 Boolean always_resize_children; 485 XtGeometryResult result; 486 XtWidgetGeometry request, return_request; 487 488 /* 489 * If we are already at the desired size then there is no need 490 * to ask our parent of we can change size 491 */ 492 if (width == XtWidth(fw) && height == XtHeight(fw)) 493 return (True); 494 495 request.width = (Dimension)width; 496 request.height = (Dimension)height; 497 request.request_mode = CWWidth | CWHeight; 498 if (query_only) 499 request.request_mode |= XtCWQueryOnly; 500 501 /* 502 * Do no invoke the resize rules if our size changes here 503 */ 504 fw->form.resize_is_no_op = True; 505 506 result = XtMakeGeometryRequest(w, &request, &return_request); 507 if (result == XtGeometryAlmost) { 508 request = return_request; 509 (void)XtMakeGeometryRequest(w, &request, &return_request); 510 always_resize_children = False; 511 } 512 else 513 always_resize_children = result == XtGeometryYes; 514 515 fw->form.resize_is_no_op = False; 516 517 if (ret_width != NULL) 518 *ret_width = request.width; 519 if (ret_height != NULL) 520 *ret_height = request.height; 521 522 return (always_resize_children); 523 } 524 525 /* 526 * Function: 527 * Layout 528 * 529 * Parameters: 530 * fw - Form widget 531 * width - unused 532 * height - "" 533 * force_relayout - will force the children to be moved, even if some 534 * go past the edge of the form 535 * 536 * Description: 537 * Moves all the children around. 538 * 539 * Returns: 540 * True if the children are allowed to move from their 541 * current locations to the new ones. 542 */ 543 /*ARGSUSED*/ 544 static Boolean 545 Layout(FormWidget fw, unsigned int width _X_UNUSED, unsigned int height _X_UNUSED, 546 Bool force_relayout) 547 { 548 int num_children = (int)fw->composite.num_children; 549 WidgetList children = fw->composite.children; 550 Widget *childP; 551 Dimension maxx, maxy; 552 Boolean ret_val; 553 554 for (childP = children; childP - children < num_children; childP++) { 555 FormConstraints form = (FormConstraints)(*childP)->core.constraints; 556 form->form.layout_state = LayoutPending; 557 } 558 559 maxx = maxy = 1; 560 for (childP = children; childP - children < num_children; childP++) { 561 if (XtIsManaged(*childP)) { 562 FormConstraints form; 563 Position x, y; 564 565 form = (FormConstraints)(*childP)->core.constraints; 566 567 LayoutChild(*childP); 568 569 x = (Position)(form->form.new_x + XtWidth(*childP) 570 + (XtBorderWidth(*childP) << 1)); 571 if (x > (int)maxx) 572 maxx = (Dimension)x; 573 574 y = (Position)(form->form.new_y + XtHeight(*childP) 575 + (XtBorderWidth(*childP) << 1)); 576 if (y > (int)maxy) 577 maxy = (Dimension)y; 578 } 579 } 580 581 fw->form.preferred_width = (maxx = (Dimension)(maxx + fw->form.default_spacing)); 582 fw->form.preferred_height = (maxy = (Dimension)(maxy + fw->form.default_spacing)); 583 584 if (fw->form.resize_in_layout) { 585 Boolean always_resize_children; 586 587 always_resize_children = 588 (Boolean)ChangeFormGeometry((Widget)fw, False, maxx, maxy, NULL, NULL); 589 590 #ifdef OLDXAW 591 fw->form.old_width = fw->core.width; 592 fw->form.old_height = fw->core.height; 593 #endif 594 595 if (force_relayout) 596 ret_val = True; 597 else 598 ret_val = always_resize_children || 599 (XtWidth(fw) >= maxx && XtHeight(fw) >= maxy); 600 601 if (ret_val) 602 ResizeChildren((Widget)fw); 603 } 604 else 605 ret_val = False; 606 607 fw->form.needs_relayout = False; 608 609 return (ret_val); 610 } 611 612 /* 613 * Function: 614 * ResizeChildren 615 * 616 * Parameters: 617 * w - form widget 618 * 619 * Description: 620 * Resizes all children to new_x and new_y. 621 */ 622 static void 623 ResizeChildren(Widget w) 624 { 625 FormWidget fw = (FormWidget)w; 626 int num_children = (int)fw->composite.num_children; 627 WidgetList children = fw->composite.children; 628 Widget *childP; 629 630 for (childP = children; childP - children < num_children; childP++) { 631 FormConstraints form; 632 Position x, y; 633 634 if (!XtIsManaged(*childP)) 635 continue; 636 637 form = (FormConstraints)(*childP)->core.constraints; 638 639 if (fw->form.old_width && fw->form.old_height) { 640 x = (Position)TransformCoord(form->form.new_x, fw->form.old_width, 641 XtWidth(fw), form->form.left); 642 y = (Position)TransformCoord(form->form.new_y, fw->form.old_height, 643 XtHeight(fw), form->form.top); 644 } 645 else { 646 x = form->form.new_x; 647 y = form->form.new_y; 648 } 649 650 if (fw->form.no_refigure) { 651 /* 652 * I am changing the widget wrapper w/o modifying the window. This is 653 * risky, but I can get away with it since I am the parent of this 654 * widget, and he must ask me for any geometry changes 655 * 656 * The window will be updated when no_refigure is set back to False 657 */ 658 XtX(*childP) = x; 659 XtY(*childP) = y; 660 } 661 else 662 XtMoveWidget(*childP, x, y); 663 } 664 } 665 666 static void 667 LayoutChild(Widget w) 668 { 669 FormConstraints form = (FormConstraints)w->core.constraints; 670 Widget ref; 671 672 switch (form->form.layout_state) { 673 case LayoutPending: 674 form->form.layout_state = LayoutInProgress; 675 break; 676 case LayoutDone: 677 return; 678 case LayoutInProgress: { 679 String subs[2]; 680 Cardinal num_subs = 2; 681 subs[0] = w->core.name; 682 subs[1] = w->core.parent->core.name; 683 684 XtAppWarningMsg(XtWidgetToApplicationContext(w), 685 "constraintLoop", "xawFormLayout", "XawToolkitError", 686 "constraint loop detected while laying out " 687 "child '%s' in FormWidget '%s'", 688 subs, &num_subs); 689 } return; 690 } 691 692 form->form.new_x = (Position)form->form.dx; 693 form->form.new_y = (Position)form->form.dy; 694 if ((ref = form->form.horiz_base) != NULL) { 695 FormConstraints ref_form = (FormConstraints)ref->core.constraints; 696 697 LayoutChild(ref); 698 form->form.new_x = (Position)(form->form.new_x 699 + (ref_form->form.new_x 700 + XtWidth(ref) 701 + (XtBorderWidth(ref) << 1))); 702 } 703 if ((ref = form->form.vert_base) != NULL) { 704 FormConstraints ref_form = (FormConstraints)ref->core.constraints; 705 706 LayoutChild(ref); 707 form->form.new_y = (Position)(form->form.new_y 708 + (ref_form->form.new_y 709 + XtHeight(ref) 710 + (XtBorderWidth(ref) << 1))); 711 } 712 713 form->form.layout_state = LayoutDone; 714 } 715 716 static int 717 TransformCoord(int loc, unsigned int old, unsigned int cnew, XtEdgeType type) 718 { 719 if (type == XtRubber) { 720 if ((int)old > 0) 721 loc = (int)(loc * ((double)cnew / (double)old)); 722 } 723 else if (type == XtChainBottom || type == XtChainRight) 724 loc += (int)cnew - (int)old; 725 726 return (loc); 727 } 728 729 static void 730 XawFormResize(Widget w) 731 { 732 FormWidget fw = (FormWidget)w; 733 WidgetList children = fw->composite.children; 734 int num_children = (int)fw->composite.num_children; 735 Widget *childP; 736 int x, y; 737 int width, height; 738 Boolean unmap = XtIsRealized(w) && w->core.mapped_when_managed && 739 XtIsManaged(w); 740 741 if (unmap) 742 XtUnmapWidget(w); 743 744 if (!fw->form.resize_is_no_op) 745 for (childP = children; childP - children < num_children; childP++) { 746 FormConstraints form = (FormConstraints)(*childP)->core.constraints; 747 748 if (!XtIsManaged(*childP)) 749 continue; 750 751 #ifndef OLDXAW 752 x = TransformCoord(form->form.virtual_x, fw->form.old_width, 753 XtWidth(fw), form->form.left); 754 y = TransformCoord(form->form.virtual_y, fw->form.old_height, 755 XtHeight(fw), form->form.top); 756 width = TransformCoord(form->form.virtual_x + 757 form->form.virtual_width + 758 (XtBorderWidth(*childP) << 1), 759 fw->form.old_width, XtWidth(fw), 760 form->form.right) - 761 (x + (XtBorderWidth(*childP) << 1)); 762 height = TransformCoord(form->form.virtual_y + 763 form->form.virtual_height + 764 (XtBorderWidth(*childP) << 1), 765 fw->form.old_height, XtHeight(fw), 766 form->form.bottom) - 767 (y + (XtBorderWidth(*childP) << 1)); 768 #else 769 x = TransformCoord(XtX(*childP), fw->form.old_width, 770 XtWidth(fw), form->form.left); 771 y = TransformCoord(XtY(*childP), fw->form.old_height, 772 XtHeight(fw), form->form.top); 773 width = TransformCoord(XtX(*childP) + form->form.virtual_width + 774 (XtBorderWidth(*childP) << 1), 775 fw->form.old_width, XtWidth(fw), 776 form->form.right) - 777 (x + (XtBorderWidth(*childP) << 1)); 778 height = TransformCoord(XtY(*childP) + form->form.virtual_height + 779 (XtBorderWidth(*childP) << 1), 780 fw->form.old_height, XtHeight(fw), 781 form->form.bottom) - 782 (y + (XtBorderWidth(*childP) << 1)); 783 form->form.virtual_width = (short)width; 784 form->form.virtual_height = (short)height; 785 #endif 786 787 width = width < 1 ? 1 : width; 788 height = height < 1 ? 1 : height; 789 790 XtConfigureWidget(*childP, 791 (Position)x, (Position)y, 792 (Dimension)width, (Dimension)height, 793 XtBorderWidth(*childP)); 794 } 795 796 if (unmap) 797 XtMapWidget(w); 798 799 #ifdef OLDXAW 800 fw->form.old_width = XtWidth(fw); 801 fw->form.old_height = XtHeight(fw); 802 #endif 803 } 804 805 /*ARGSUSED*/ 806 static XtGeometryResult 807 XawFormGeometryManager(Widget w, XtWidgetGeometry *request, 808 XtWidgetGeometry *reply _X_UNUSED) 809 { 810 Dimension old_width, old_height; 811 FormWidget fw = (FormWidget)XtParent(w); 812 FormConstraints form = (FormConstraints)w->core.constraints; 813 XtWidgetGeometry allowed; 814 XtGeometryResult ret_val; 815 816 if ((request->request_mode & (unsigned)~(XtCWQueryOnly | CWWidth | CWHeight)) 817 || !form->form.allow_resize) { 818 /* If GeometryManager is invoked during a SetValues call on a child 819 * then it is necessary to compute a new layout if ConstraintSetValues 820 * allowed any constraint changes 821 */ 822 if (fw->form.needs_relayout) 823 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) 824 (fw, 0, 0, True); 825 return (XtGeometryNo); 826 } 827 828 if (request->request_mode & CWWidth) 829 allowed.width = request->width; 830 else 831 allowed.width = XtWidth(w); 832 833 if (request->request_mode & CWHeight) 834 allowed.height = request->height; 835 else 836 allowed.height = XtHeight(w); 837 838 if (allowed.width == XtWidth(w) && allowed.height == XtHeight(w)) { 839 /* If GeometryManager is invoked during a SetValues call on a child 840 * then it is necessary to compute a new layout if ConstraintSetValues 841 * allowed any constraint changes 842 */ 843 if (fw->form.needs_relayout) 844 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) 845 (fw, 0, 0, True); 846 return (XtGeometryNo); 847 } 848 849 /* 850 * Remember the old size, and then set the size to the requested size 851 */ 852 old_width = XtWidth(w); 853 old_height = XtHeight(w); 854 XtWidth(w) = allowed.width; 855 XtHeight(w) = allowed.height; 856 857 if (request->request_mode & XtCWQueryOnly) { 858 Boolean always_resize_children; 859 Dimension ret_width, ret_height; 860 861 fw->form.resize_in_layout = False; 862 863 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) 864 (fw, XtWidth(w), XtHeight(w), False); 865 866 /* 867 * Reset the size of this child back to what it used to be 868 */ 869 XtWidth(w) = old_width; 870 XtHeight(w) = old_height; 871 872 fw->form.resize_in_layout = True; 873 874 always_resize_children = (Boolean)ChangeFormGeometry(w, True, 875 fw->form.preferred_width, 876 fw->form.preferred_height, 877 &ret_width, &ret_height); 878 879 if (always_resize_children 880 || (ret_width >= fw->form.preferred_width 881 && ret_height >= fw->form.preferred_height)) 882 ret_val = XtGeometryYes; 883 else 884 ret_val = XtGeometryNo; 885 } 886 else { 887 if ((*((FormWidgetClass)fw->core.widget_class)->form_class.layout) 888 (fw, XtWidth(w), XtHeight(w), False)) { 889 Widget *childP; 890 int num_children = (int)fw->composite.num_children; 891 WidgetList children = fw->composite.children; 892 893 if (fw->form.no_refigure) { 894 /* 895 * I am changing the widget wrapper w/o modifying the window. 896 * This is risky, but I can get away with it since I am the 897 * parent of this widget, and he must ask me for any geometry 898 * changes 899 * 900 * The window will be updated when no_refigure is set back 901 * to False 902 */ 903 form->form.deferred_resize = True; 904 ret_val = XtGeometryDone; 905 } 906 else 907 ret_val = XtGeometryYes; 908 909 /* 910 * Resets everything. 911 */ 912 fw->form.old_width = XtWidth(fw); 913 fw->form.old_height = XtHeight(fw); 914 for (childP = children; childP - children < num_children; childP++) { 915 Widget nw = *childP; 916 917 if (XtIsManaged(nw)) { 918 FormConstraints nform = (FormConstraints)nw->core.constraints; 919 920 #ifndef OLDXAW 921 nform->form.virtual_x = XtX(nw); 922 nform->form.virtual_y = XtY(nw); 923 #endif 924 nform->form.virtual_width = (short)XtWidth(nw); 925 nform->form.virtual_height = (short)XtHeight(nw); 926 } 927 } 928 } 929 else { 930 XtWidth(w) = old_width; 931 XtHeight(w) = old_height; 932 ret_val = XtGeometryNo; 933 } 934 } 935 936 return (ret_val); 937 } 938 939 /*ARGSUSED*/ 940 static Boolean 941 XawFormSetValues(Widget current _X_UNUSED, Widget request _X_UNUSED, Widget cnew _X_UNUSED, 942 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 943 { 944 #ifndef OLDXAW 945 FormWidget f_old = (FormWidget)current; 946 FormWidget f_new = (FormWidget)cnew; 947 948 if (f_old->core.background_pixmap != f_new->core.background_pixmap) { 949 XawPixmap *opix, *npix; 950 951 opix = XawPixmapFromXPixmap(f_old->core.background_pixmap, XtScreen(f_old), 952 f_old->core.colormap, (int)f_old->core.depth); 953 npix = XawPixmapFromXPixmap(f_new->core.background_pixmap, XtScreen(f_new), 954 f_new->core.colormap, (int)f_new->core.depth); 955 if ((npix && npix->mask) || (opix && opix->mask)) 956 XawReshapeWidget(cnew, npix); 957 } 958 #endif /* OLDXAW */ 959 960 return (False); 961 } 962 963 /* ARGSUSED */ 964 static void 965 XawFormConstraintInitialize(Widget request _X_UNUSED, Widget cnew, 966 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 967 { 968 FormConstraints form = (FormConstraints)cnew->core.constraints; 969 FormWidget fw = (FormWidget)cnew->core.parent; 970 971 #ifndef OLDXAW 972 form->form.virtual_x = XtX(cnew); 973 form->form.virtual_y = XtY(cnew); 974 #endif 975 form->form.virtual_width = (short)XtWidth(cnew); 976 form->form.virtual_height = (short)XtHeight(cnew); 977 978 if (form->form.dx == default_value) 979 form->form.dx = fw->form.default_spacing; 980 981 if (form->form.dy == default_value) 982 form->form.dy = fw->form.default_spacing; 983 984 form->form.deferred_resize = False; 985 } 986 987 /*ARGSUSED*/ 988 static Boolean 989 XawFormConstraintSetValues(Widget current, Widget request _X_UNUSED, Widget cnew, 990 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 991 { 992 FormConstraints cfc = (FormConstraints)current->core.constraints; 993 FormConstraints nfc = (FormConstraints)cnew->core.constraints; 994 995 if (cfc->form.top != nfc->form.top || cfc->form.bottom != nfc->form.bottom 996 || cfc->form.left != nfc->form.left || cfc->form.right != nfc->form.right 997 || cfc->form.dx != nfc->form.dx || cfc->form.dy != nfc->form.dy 998 || cfc->form.horiz_base != nfc->form.horiz_base 999 || cfc->form.vert_base != nfc->form.vert_base) { 1000 FormWidget fp = (FormWidget)XtParent(cnew); 1001 1002 /* If there are no subclass ConstraintSetValues procedures remaining 1003 * to be invoked, and if there is no geometry request about to be 1004 * made, then invoke the new layout now; else defer it 1005 */ 1006 if (XtClass(XtParent(cnew)) == formWidgetClass 1007 && XtX(current) == XtX(cnew) 1008 && XtY(current) == XtY(cnew) 1009 && XtWidth(current) == XtWidth(cnew) 1010 && XtHeight(current) == XtHeight(cnew) 1011 && XtBorderWidth(current) == XtBorderWidth(cnew)) 1012 Layout(fp, 0, 0, True); 1013 else 1014 fp->form.needs_relayout = True; 1015 } 1016 1017 return (False); 1018 } 1019 1020 static void 1021 XawFormChangeManaged(Widget w) 1022 { 1023 FormWidget fw = (FormWidget)w; 1024 WidgetList children, childP; 1025 int num_children = (int)fw->composite.num_children; 1026 1027 (*((FormWidgetClass)w->core.widget_class)->form_class.layout) 1028 (fw, XtWidth(w), XtHeight(w), True); 1029 1030 fw->form.old_width = XtWidth(w); 1031 fw->form.old_height = XtHeight(w); 1032 for (children = childP = fw->composite.children; 1033 childP - children < num_children; 1034 childP++) { 1035 FormConstraints form; 1036 Widget child = *childP; 1037 if (!XtIsManaged(child)) 1038 continue; 1039 form = (FormConstraints)child->core.constraints; 1040 #ifndef OLDXAW 1041 form->form.virtual_x = XtX(child); 1042 form->form.virtual_y = XtY(child); 1043 #endif 1044 form->form.virtual_width = (short)XtWidth(child); 1045 form->form.virtual_height = (short)XtHeight(child); 1046 } 1047 } 1048 1049 static XtGeometryResult 1050 XawFormQueryGeometry(Widget widget, XtWidgetGeometry *request, 1051 XtWidgetGeometry *reply) 1052 { 1053 FormWidget w = (FormWidget)widget; 1054 1055 reply->width = w->form.preferred_width; 1056 reply->height = w->form.preferred_height; 1057 reply->request_mode = CWWidth | CWHeight; 1058 1059 if ((request->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight) 1060 && request->width == reply->width 1061 && request->height == reply->height) 1062 return (XtGeometryYes); 1063 else if (reply->width == XtWidth(w) && reply->height == XtHeight(w)) 1064 return (XtGeometryNo); 1065 1066 return (XtGeometryAlmost); 1067 } 1068 1069 /* 1070 * Public routines 1071 */ 1072 /* 1073 * Set or reset figuring (ignored if not realized) 1074 */ 1075 void 1076 XawFormDoLayout(Widget w, 1077 #if NeedWidePrototypes 1078 Bool force 1079 #else 1080 Boolean force 1081 #endif 1082 ) 1083 { 1084 Widget *childP; 1085 FormWidget fw = (FormWidget)w; 1086 int num_children = (int)fw->composite.num_children; 1087 WidgetList children = fw->composite.children; 1088 1089 if ((fw->form.no_refigure = !force) == True || !XtIsRealized(w)) 1090 return; 1091 1092 for (childP = children; childP - children < num_children; childP++) { 1093 Widget nw = *childP; 1094 1095 if (XtIsManaged(nw)) { 1096 FormConstraints form = (FormConstraints)nw->core.constraints; 1097 1098 /* 1099 * Xt Configure widget is too smart, and optimizes out 1100 * my changes 1101 */ 1102 XMoveResizeWindow(XtDisplay(nw), XtWindow(nw), 1103 XtX(nw), XtY(nw), XtWidth(nw), XtHeight(nw)); 1104 1105 if (form) 1106 if (form->form.deferred_resize && 1107 XtClass(nw)->core_class.resize != NULL) { 1108 (*(XtClass(nw)->core_class.resize))(nw); 1109 form->form.deferred_resize = False; 1110 } 1111 } 1112 } 1113 } 1114