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