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