1/* 2 * 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 */ 25 26#ifdef HAVE_CONFIG_H 27# include "config.h" 28#endif 29 30#include <X11/Intrinsic.h> 31#include <X11/Xutil.h> 32#include <X11/Xos.h> 33#include <X11/Shell.h> 34#include <X11/StringDefs.h> 35 36#include <X11/Xaw/Cardinals.h> 37#include <X11/Xaw/Dialog.h> 38 39#include <stdio.h> 40#include <stdlib.h> 41#include <X11/Xmu/Error.h> 42 43#include "editresP.h" 44 45static WNode * FindWidgetFromWindowGivenNode ( WNode * node, Window win ); 46static WidgetResources * ParseResources ( GetResourcesInfo * info, 47 char **error ); 48static int CompareResourceEntries ( const void *e1, 49 const void *e2 ); 50static void AddResource ( ResourceInfo * res_info, 51 WidgetResourceInfo * resource ); 52static void FreeResources ( WidgetResources * resources ); 53 54 55/* Function Name: SetMessage(w, str) 56 * Description: shows the message to the user. 57 * Arguments: w - a label widget to show the message in. 58 * str - the string to show. 59 * Returns: none. 60 */ 61 62void 63SetMessage(Widget w, const char *str) 64{ 65 Arg args[1]; 66 67 XtSetArg(args[0], XtNlabel, str); 68 XtSetValues(w, args, ONE); 69} 70 71/* Function Name: GetAllStrings 72 * Description: Returns a list of strings that have been broken up by 73 * the character specified. 74 * Arguments: in - the string to parse. 75 * sep - the separator character. 76 * out - the strings to send out. 77 * num - the number of strings in out. 78 * Returns: none 79 */ 80 81void 82GetAllStrings(char *in, char sep, char ***out, int *num) 83{ 84 int size, i; 85 char * ptr; 86 87 if (*in == sep) /* jump over first char if it is the sep. */ 88 in++; 89 90 /* 91 * count the number of strings. 92 */ 93 94 for (*num = 1, ptr = in; (ptr = strchr(ptr, sep)) != NULL; (*num)++) 95 ptr++; 96 97/* 98 * Create Enough space for pointers and string. 99 */ 100 101 size = (sizeof(char *) * *num) + (sizeof(char) * (strlen(in) + 1)); 102 *out = (char **) XtMalloc( (Cardinal) size); 103 104 ptr = (char *) (*out + *num); 105 strcpy(ptr, in); 106 107/* 108 * Change all `sep' characters to '\0' and stuff the pointer into 109 * the next pointer slot. 110 */ 111 112 i = 1; 113 (*out)[0] = ptr; 114 while (TRUE) { 115 if ((ptr = strchr(ptr, sep)) == NULL) 116 break; 117 118 *ptr++ = '\0'; 119 (*out)[i++] = ptr; 120 } 121 122/* 123 * If last string is empty then strip it off. 124 */ 125 126 if ( *((*out)[i - 1]) == '\0' ) 127 (*num)--; 128} 129 130/* Function Name: AddString 131 * Description: Mallocs and strcats the string onto the end of 132 * the given string. 133 * Arguments: str - string to add on to. 134 * add - string to add. 135 * Returns: none. 136 */ 137 138void 139AddString(char ** str, const char *add) 140{ 141 int len_str, len_add; 142 char * ptr; 143 144 len_str = ((*str) ? strlen(*str) : 0); 145 len_add = strlen(add); 146 147 *str = XtRealloc(*str, sizeof(char) * (len_str + len_add + 1)); 148 ptr = *str + len_str; 149 strcpy(ptr, add); 150} 151 152/* Function Name: FindNode 153 * Description: Finds a node give the top node, and a node id number. 154 * Arguments: top_node - the top node. 155 * id - the node id. 156 * Returns: node. 157 */ 158 159WNode * 160FindNode(WNode *top_node, unsigned long *ids, Cardinal number) 161{ 162 Cardinal i, j; 163 WNode *node; 164 165 if (top_node == NULL) 166 return(NULL); 167 168 if (ids[0] != top_node->id) 169 return(NULL); 170 171 for (node = top_node, i = 1 ; i < number; i++) { 172 Boolean found_it = FALSE; 173 174 for (j = 0; j < node->num_children; j++) { 175 if (node->children[j]->id == ids[i]) { 176 node = node->children[j]; 177 found_it = TRUE; 178 break; 179 } 180 } 181 if (!found_it) 182 return(NULL); 183 } 184 return(node); 185} 186 187/* Function Name: FindWidgetFromWindow 188 * Description: finds a widget in the current tree given its window id. 189 * Arguments: tree_info - information about this tree. 190 * win - window to search for. 191 * Returns: node - the node corrosponding to this widget. 192 */ 193 194WNode * 195FindWidgetFromWindow(TreeInfo *tree_info, Window win) 196{ 197 if (tree_info == NULL) 198 return(NULL); 199 200 return(FindWidgetFromWindowGivenNode(tree_info->top_node, win)); 201} 202 203/* Function Name: FindWidgetFromWindowGivenNode 204 * Description: finds a widget in the current tree given its window id. 205 * Arguments: node - current node. 206 * win - window to search for. 207 * Returns: node - the node corrosponding to this widget. 208 */ 209 210static WNode * 211FindWidgetFromWindowGivenNode(WNode *node, Window win) 212{ 213 Cardinal i; 214 WNode * ret_node; 215 216 if (node->window == win) 217 return(node); 218 219 for (i = 0; i < node->num_children; i++) { 220 ret_node = FindWidgetFromWindowGivenNode(node->children[i], win); 221 if (ret_node != NULL) 222 return(ret_node); 223 } 224 return(NULL); 225} 226 227/* Function Name: HandleXErrors 228 * Description: Handles error codes from the server. 229 * Arguments: display - the display. 230 * error - error information. 231 * Returns: none. 232 */ 233 234/* ARGSUSED */ 235int 236HandleXErrors(Display *display, XErrorEvent *error) 237{ 238 if (error->serial != global_serial_num) { 239 (*global_old_error_handler) (display, error); 240 return(0); 241 } 242 243 if (error->error_code == BadWindow) 244 global_error_code = NO_WINDOW; 245 else { 246 if (XmuPrintDefaultErrorMessage(display, error, stderr) != 0) 247 exit(1); 248 } 249 return(0); 250} 251 252/* Function Name: _DumpTreeToFile 253 * Description: Dumps the widget tree to a file 254 * Arguments: w - a random widget in the application on the 255 * currently active display 256 * tree_ptr - pointer to the widget tree info. 257 * filename - name of the file. 258 * Returns: none. 259 */ 260 261/* ARGSUSED */ 262 263void 264_DumpTreeToFile(Widget w, XtPointer tree_ptr, XtPointer filename) 265{ 266 TreeInfo * tree_info = (TreeInfo *) tree_ptr; 267 FILE * fp; 268 269 if (tree_info == NULL) { 270 SetMessage(global_screen_data.info_label, 271 res_labels[17]); 272 return; 273 } 274 275 if ( (fp = fopen((char *)filename, "w")) == NULL ) { 276 char buf[BUFSIZ]; 277 278 snprintf(buf, sizeof(buf), res_labels[24], (char *)filename); 279 SetMessage(global_screen_data.info_label, buf); 280 return; 281 } 282 283 PerformTreeToFileDump(tree_info->top_node, 0, fp); 284 fclose(fp); 285} 286 287/************************************************************ 288 * 289 * The file dialog boxes are handled with this code. 290 * 291 * It automatically calls the function specified when the 292 * user selects okay, or hits <CR>. 293 * 294 * A translation is required in the app-defaults file. 295 * 296 ************************************************************/ 297 298/* Function Name: _PopupFileDialog 299 * Description: Puts up a dialog box to get the filename. 300 * Arguments: str - message. 301 * default_value - the default value of the filename; 302 * func - function to call when filename has been entered. 303 * data - generic data to pass to func. 304 * Returns: none 305 */ 306 307static XContext file_dialog_context = None; 308 309typedef struct _FileDialogInfo { 310 XtCallbackProc func; 311 XtPointer data; 312} FileDialogInfo; 313 314void 315_PopupFileDialog(Widget w, const char *str, const char *default_value, 316 XtCallbackProc func, XtPointer data) 317{ 318 FileDialogInfo * file_info; 319 Widget shell, dialog; 320 Arg args[2]; 321 Cardinal num_args; 322 323 if (file_dialog_context == None) 324 file_dialog_context = XUniqueContext(); 325 326 shell = XtCreatePopupShell("fileDialog", transientShellWidgetClass, w, 327 NULL, ZERO); 328 329 num_args = 0; 330 XtSetArg(args[num_args], XtNlabel, str); num_args++; 331 XtSetArg(args[num_args], XtNvalue, default_value); num_args++; 332 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass, 333 shell, args, num_args); 334 335 file_info = XtNew(FileDialogInfo); 336 337 file_info->func = func; 338 file_info->data = data; 339 340 if (XSaveContext(XtDisplay(dialog), (Window) dialog, file_dialog_context, 341 (XPointer) file_info) != 0) { 342 SetMessage(global_screen_data.info_label, 343 "Error while trying to save Context\nAborting file dialog popup."); 344 XtDestroyWidget(shell); 345 return; 346 } 347 348 XawDialogAddButton(dialog, "okay", _PopdownFileDialog, (XtPointer) TRUE); 349 XawDialogAddButton(dialog, "cancel", _PopdownFileDialog,(XtPointer) FALSE); 350 351 PopupCentered(NULL, shell, XtGrabNone); 352} 353 354/* Function Name: PopupCentered 355 * Description: Pops up the window specified under the location passed 356 * in the event, or under the cursor. 357 * Arguments: event - the event that we should use. 358 * w - widget to popup. 359 * mode - mode to pop it up in. 360 * Returns: none 361 */ 362 363void 364PopupCentered(XEvent *event, Widget w, XtGrabKind mode) 365{ 366 Boolean get_from_cursor = FALSE; 367 Arg args[3]; 368 Cardinal num_args; 369 Dimension width, height, b_width; 370 int x, y, max_x, max_y; 371 372 XtRealizeWidget(w); 373 374 if (event == NULL) 375 get_from_cursor = TRUE; 376 else { 377 switch (event->type) { 378 case ButtonPress: 379 case ButtonRelease: 380 x = event->xbutton.x_root; 381 y = event->xbutton.y_root; 382 break; 383 case KeyPress: 384 case KeyRelease: 385 x = event->xkey.x_root; 386 y = event->xkey.y_root; 387 break; 388 default: 389 get_from_cursor = TRUE; 390 break; 391 } 392 } 393 394 if (get_from_cursor) { 395 Window root, child; 396 int win_x, win_y; 397 unsigned int mask; 398 399 XQueryPointer(XtDisplay(w), XtWindow(w), 400 &root, &child, &x, &y, &win_x, &win_y, &mask); 401 } 402 403 num_args = 0; 404 XtSetArg(args[num_args], XtNwidth, &width); num_args++; 405 XtSetArg(args[num_args], XtNheight, &height); num_args++; 406 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++; 407 XtGetValues(w, args, num_args); 408 409 width += 2 * b_width; 410 height += 2 * b_width; 411 412 x -= ((int) width/2); 413 if (x < 0) 414 x = 0; 415 if ( x > (max_x = (int) (XtScreen(w)->width - width)) ) 416 x = max_x; 417 418 y -= ( (Position) height/2 ); 419 if (y < 0) 420 y = 0; 421 if ( y > (max_y = (int) (XtScreen(w)->height - height)) ) 422 y = max_y; 423 424 num_args = 0; 425 XtSetArg(args[num_args], XtNx, x); num_args++; 426 XtSetArg(args[num_args], XtNy, y); num_args++; 427 XtSetValues(w, args, num_args); 428 429 XtPopup(w, mode); 430} 431 432/* Function Name: _PopdownFileDialog 433 * Description: Destroys the file dialog, and calls the correct function. 434 * Arguments: w - a child of the dialog widget. 435 * client_data - TRUE if command was successful. 436 * junk - ** UNUSED **. 437 * Returns: none. 438 */ 439 440/* ARGSUSED */ 441 442void 443_PopdownFileDialog(Widget w, XtPointer client_data, XtPointer junk) 444{ 445 Widget dialog = XtParent(w); 446 XPointer file_info_ptr; 447 FileDialogInfo * file_info; 448 449 if (XFindContext(XtDisplay(dialog), (Window) dialog, file_dialog_context, 450 &file_info_ptr) == XCNOENT) { 451 SetMessage(global_screen_data.info_label, 452 "Error while trying to find Context\nAborting..."); 453 } 454 455 (void) XDeleteContext(XtDisplay(dialog), (Window)dialog, 456 file_dialog_context); 457 458 file_info = (FileDialogInfo *) file_info_ptr; 459 460 if ( ((Boolean)(long) client_data) == TRUE ) { 461 String filename = XawDialogGetValueString(dialog); 462 463 (*file_info->func)(w, file_info->data, filename); /* call handler */ 464 } 465 466 XtFree( (XtPointer) file_info); /* Free data. */ 467 468 XtPopdown(XtParent(dialog)); 469 XtDestroyWidget(XtParent(dialog)); /* Remove file dialog. */ 470} 471 472/************************************************************ 473 * 474 * Functions for dealing with the Resource Box. 475 * 476 ************************************************************/ 477 478/* Function Name: GetNamesAndClasses 479 * Description: Gets a list of names and classes for this widget. 480 * Arguments: node - this widget's node. 481 * names, classes - list of names and classes. ** RETURNED ** 482 * Returns: none. 483 */ 484 485void 486GetNamesAndClasses(WNode *node, char ***names, char ***classes) 487{ 488 int i, total_widgets; 489 WNode * temp = node; 490 491 for (total_widgets = 1 ; temp->parent != NULL ; 492 total_widgets++, temp = temp->parent) {} 493 494 *names = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1)); 495 *classes = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1)); 496 497 (*names)[total_widgets] = (*classes)[total_widgets] = NULL; 498 499 for ( i = (total_widgets - 1); i >= 0 ; node = node->parent, i--) { 500 (*names)[i] = node->name; 501 (*classes)[i] = node->class; 502 } 503} 504 505/* Function Name: HandleGetResources 506 * Description: Gets the resources. 507 * Arguments: event - the information from the client. 508 * Returns: an error message to display. 509 */ 510 511char * 512HandleGetResources(Event *event) 513{ 514 GetResourcesEvent * get_event = (GetResourcesEvent *) event; 515 char buf[BUFSIZ], * errors = NULL; 516 int i; 517 WNode * node; 518 519 for (i = 0; i < (int)get_event->num_entries; i++) { 520 node = FindNode(global_tree_info->top_node, 521 get_event->info[i].widgets.ids, 522 get_event->info[i].widgets.num_widgets); 523 524 if (node == NULL) { 525 snprintf(buf, sizeof(buf), res_labels[16]); 526 AddString(&errors, buf); 527 continue; 528 } 529 530 if (node->resources != NULL) 531 FreeResources(node->resources); 532 533 if (!get_event->info[i].error) { 534 node->resources = ParseResources(get_event->info + i, &errors); 535 CreateResourceBox(node, &errors); 536 } 537 else { 538 AddString(&errors, get_event->info[i].message); 539 AddString(&errors, "\n"); 540 } 541 } 542 543 return(errors); 544} 545 546/* Function Name: CreateResourceBox 547 * Description: Creates a resource box for the widget specified. 548 * Arguments: node - the node of the widget in question. 549 * errors - an error string. 550 * Returns: none. 551 */ 552 553void 554CreateResourceBox(WNode *node, char **errors) 555{ 556 WidgetResources * resources = node->resources; 557 char ** names, ** cons_names; 558 int i; 559 560 if (global_resource_box_up) { 561 AddString(errors, res_labels[34]); 562 return; 563 } 564 else 565 global_resource_box_up = TRUE; 566 567 if (resources->num_normal > 0) { 568 names = (char **) XtMalloc(sizeof(char *) * 569 (resources->num_normal + 1)); 570 for (i = 0 ; i < resources->num_normal ; i++) 571 names[i] = resources->normal[i].name; 572 names[i] = NULL; 573 } 574 else 575 names = NULL; 576 577 if (resources->num_constraint > 0) { 578 cons_names = (char **) XtMalloc(sizeof(char *) * 579 (resources->num_constraint + 1)); 580 581 for (i = 0 ; i < resources->num_constraint ; i++) 582 cons_names[i] = resources->constraint[i].name; 583 cons_names[i] = NULL; 584 } 585 else 586 cons_names = NULL; 587 588 CreateResourceBoxWidgets(node, names, cons_names); 589} 590 591/* Function Name: ParseResources 592 * Description: Parses the resource values returned from the client 593 * into a resources structure. 594 * Arguments: info - info about a widget's resources. 595 * error - where to place error info. 596 * Returns: The resource information. 597 */ 598 599static WidgetResources * 600ParseResources(GetResourcesInfo *info, char **error) 601{ 602 WidgetResources * resources; 603 WidgetResourceInfo * normal; 604 int i; 605 606 resources = (WidgetResources *) XtMalloc(sizeof(WidgetResources)); 607 608 /* 609 * Allocate enough space for both the normal and constraint resources, 610 * then add the normal resources from the top, and the constraint resources 611 * from the bottom. This assures that enough memory is allocated, and 612 * that there is no overlap. 613 */ 614 615 resources->normal = (WidgetResourceInfo *) 616 XtMalloc(sizeof(WidgetResourceInfo) * info->num_resources); 617 618 normal = resources->normal; 619 resources->constraint = resources->normal + info->num_resources - 1; 620 621 resources->num_constraint = resources->num_normal = 0; 622 623 for (i = 0; i < (int)info->num_resources; i++) { 624 switch((int) info->res_info[i].res_type) { 625 case NormalResource: 626 resources->num_normal++; 627 AddResource(info->res_info + i, normal++); 628 break; 629 case ConstraintResource: 630 resources->num_constraint++; 631 AddResource(info->res_info + i, resources->constraint--); 632 break; 633 default: 634 { 635 char buf[BUFSIZ]; 636 snprintf(buf, sizeof(buf), "Unknown resource type %d\n", 637 info->res_info[i].res_type); 638 AddString(error, buf); 639 } 640 break; 641 } 642 } 643 644 /* 645 * Sort the resources alphabetically. 646 */ 647 648 qsort(resources->normal, resources->num_normal, 649 sizeof(WidgetResourceInfo), CompareResourceEntries); 650 651 if (resources->num_constraint > 0) { 652 resources->constraint++; 653 qsort(resources->constraint, resources->num_constraint, 654 sizeof(WidgetResourceInfo), CompareResourceEntries); 655 } 656 else 657 resources->constraint = NULL; 658 659 return(resources); 660} 661 662/* Function Name: CompareResourceEntries 663 * Description: Compares two resource entries. 664 * Arguments: e1, e2 - the entries to compare. 665 * Returns: an integer >, < or = 0. 666 */ 667 668static int 669CompareResourceEntries(const void *e1, const void *e2) 670{ 671 return (strcmp(((WidgetResourceInfo *)e1)->name, 672 ((WidgetResourceInfo *)e2)->name)); 673} 674 675/* Function Name: AddResource 676 * Description: Parses the resource string a stuffs in individual 677 * parts into the resource info struct. 678 * Arguments: res_info - the resource info from the event. 679 * resource - location to stuff the resource into. 680 * Returns: none. 681 */ 682 683static void 684AddResource(ResourceInfo *res_info, WidgetResourceInfo *resource) 685{ 686 resource->name = res_info->name; 687 res_info->name = NULL; /* Keeps it from being deallocated. */ 688 resource->class = res_info->class; 689 res_info->class = NULL; /* Keeps it from being deallocated. */ 690 resource->type = res_info->type; 691 res_info->type = NULL; /* Keeps it from being deallocated. */ 692} 693 694 695/* Function Name: FreeResources 696 * Description: frees the resource information. 697 * Arguments: resources. 698 * Returns: none. 699 */ 700 701static void 702FreeResources(WidgetResources *resources) 703{ 704 int i; 705 706 if (resources->num_normal > 0) { 707 for (i = 0; i < resources->num_normal; i++) { 708 XtFree(resources->normal[i].name); 709 XtFree(resources->normal[i].class); 710 XtFree(resources->normal[i].type); 711 } 712 XFree((char *)resources->normal); 713 } 714 715 if (resources->num_constraint > 0) { 716 for (i = 0; i < resources->num_constraint; i++) { 717 XtFree(resources->constraint[i].name); 718 XtFree(resources->constraint[i].class); 719 XtFree(resources->constraint[i].type); 720 } 721 XFree((char *)resources->constraint); 722 } 723 724 XFree((char *)resources); 725} 726 727 728/* Function Name: CheckDatabase 729 * Description: Checks to see if the node is in the database. 730 * Arguments: db - the db to check 731 * names, classes - names and classes, represented as quarks. 732 * Returns: True if this entry is found. 733 */ 734 735Boolean 736CheckDatabase(XrmDatabase db, XrmQuarkList names, XrmQuarkList classes) 737{ 738 XrmRepresentation junk; 739 XrmValue garbage; 740 741 return(XrmQGetResource(db, names, classes, &junk, &garbage)); 742} 743 744/* Function Name: Quarkify 745 * Description: Quarkifies the string list specified. 746 * Arguments: list - list of strings to quarkify 747 * ptr - an additional string to quarkify. 748 * Returns: none. 749 */ 750 751XrmQuarkList 752Quarkify(char **list, const char *ptr) 753{ 754 int i; 755 char ** tlist; 756 XrmQuarkList quarks, tquarks; 757 758 for (i = 0, tlist = list; *tlist != NULL; tlist++, i++) {} 759 if (ptr != NULL) 760 i++; 761 i++; /* leave space for NULLQUARK */ 762 763 quarks = (XrmQuarkList) XtMalloc(sizeof(XrmQuark) * i); 764 765 for (tlist = list, tquarks = quarks; *tlist != NULL; tlist++, tquarks++) 766 *tquarks = XrmStringToQuark(*tlist); 767 768 if (ptr != NULL) 769 *tquarks++ = XrmStringToQuark(ptr); 770 771 *tquarks = NULLQUARK; 772 return(quarks); 773} 774 775/* Function Name: ExecuteOverAllNodes 776 * Description: Executes the given function over all nodes. 777 * Arguments: top_node - top node of the tree. 778 * func - the function to execute. 779 * data - a data pointer to pass to the function. 780 * Returns: none 781 */ 782 783void 784ExecuteOverAllNodes(WNode *top_node, void (*func)(WNode *, XtPointer), 785 XtPointer data) 786{ 787 Cardinal i; 788 789 (*func)(top_node, data); 790 791 for (i = 0; i < top_node->num_children; i++) 792 ExecuteOverAllNodes(top_node->children[i], func, data); 793} 794 795/* Function Name: InsertWidgetFromNode 796 * Description: Inserts the widget info for this widget represented 797 * by this node. 798 * Arguments: stream - the stream to insert it info into. 799 * none - the widget node to insert. 800 * Returns: none 801 */ 802 803void 804InsertWidgetFromNode(ProtocolStream *stream, WNode *node) 805{ 806 WNode *temp; 807 unsigned long * widget_list; 808 register int i, num_widgets; 809 810 for (temp = node, i = 0; temp != NULL; temp = temp->parent, i++) {} 811 812 num_widgets = i; 813 widget_list = (unsigned long *) 814 XtMalloc(sizeof(unsigned long) * num_widgets); 815 816 /* 817 * Put the widgets into the list. 818 * Make sure that they are inserted in the list from parent -> child. 819 */ 820 821 for (i--, temp = node; temp != NULL; temp = temp->parent, i--) 822 widget_list[i] = temp->id; 823 824 _XEditResPut16(stream, num_widgets); /* insert number of widgets. */ 825 for (i = 0; i < num_widgets; i++) /* insert Widgets themselves. */ 826 _XEditResPut32(stream, widget_list[i]); 827 828 XtFree((char *)widget_list); 829} 830 831/* Function Name: GetFailureMesssage 832 * Description: returns the message returned from a failed request. 833 * Arguments: stream - the protocol stream containing the message. 834 * Returns: message to show. 835 */ 836 837char * 838GetFailureMessage(ProtocolStream *stream) 839{ 840 char * return_str; 841 842 if (_XEditResGetString8(stream, &return_str)) 843 return(return_str); 844 845 return(XtNewString(res_labels[35])); 846} 847 848/* Function Name: ProtocolFailure 849 * Description: Gets the version of the protocol the client is 850 * willing to speak. 851 * Arguments: stream - the protocol stream containing the message. 852 * Returns: message to show. 853 */ 854 855char * 856ProtocolFailure(ProtocolStream *stream) 857{ 858 char buf[BUFSIZ]; 859 unsigned char version; 860 const char* old_version_string; 861 862 if (!_XEditResGet8(stream, &version)) 863 return(XtNewString(res_labels[35])); 864 865 switch ((int)version) { 866 case PROTOCOL_VERSION_ONE_POINT_ZERO: old_version_string = "1.0"; break; 867 default: old_version_string = "1.0"; 868 } 869 870 snprintf(buf, sizeof(buf), res_labels[36], 871 CURRENT_PROTOCOL_VERSION_STRING, old_version_string); 872 return(XtNewString(buf)); 873} 874 875