MultiSrc.c revision c8571806
1/* 2 * Copyright 1991 by OMRON Corporation 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name OMRON not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. OMRON makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Authors: Chris Peterson MIT X Consortium 23 * Li Yuhong OMRON Corporation 24 * Frank Sheeran OMRON Corporation 25 * 26 * Much code taken from X11R3 String and Disk Sources. 27 */ 28 29/* 30 31Copyright 1991, 1994, 1998 The Open Group 32 33Permission to use, copy, modify, distribute, and sell this software and its 34documentation for any purpose is hereby granted without fee, provided that 35the above copyright notice appear in all copies and that both that 36copyright notice and this permission notice appear in supporting 37documentation. 38 39The above copyright notice and this permission notice shall be included in 40all copies or substantial portions of the Software. 41 42THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 46AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 47CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 48 49Except as contained in this notice, the name of The Open Group shall not be 50used in advertising or otherwise to promote the sale, use or other dealings 51in this Software without prior written authorization from The Open Group. 52 53*/ 54 55#ifdef HAVE_CONFIG_H 56#include <config.h> 57#endif 58#include <stdio.h> 59#include <stdlib.h> 60#include <ctype.h> 61#include <errno.h> 62#include <X11/IntrinsicP.h> 63#include <X11/StringDefs.h> 64#include <X11/Xfuncs.h> 65#include <X11/Xos.h> 66#include <X11/Xmu/CharSet.h> 67#include <X11/Xmu/Misc.h> 68#include <X11/Xaw/XawInit.h> 69#include <X11/Xaw/MultiSrcP.h> 70#include <X11/Xaw/XawImP.h> 71#include "XawI18n.h" 72#include "Private.h" 73 74#include <sys/types.h> 75#include <sys/stat.h> 76#include <fcntl.h> 77 78#define MAGIC_VALUE ((XawTextPosition)-1) 79#define streq(a, b) (strcmp((a), (b)) == 0) 80 81 82/* 83 * Class Methods 84 */ 85static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int); 86static int ReplaceText(Widget, XawTextPosition, XawTextPosition, 87 XawTextBlock*); 88static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, 89 XawTextScanDirection, int, Bool); 90static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, 91 XawTextBlock*); 92static void XawMultiSrcClassInitialize(void); 93static void XawMultiSrcDestroy(Widget); 94static void XawMultiSrcInitialize(Widget, Widget, ArgList, Cardinal*); 95static Boolean XawMultiSrcSetValues(Widget, Widget, Widget, 96 ArgList, Cardinal*); 97static void XawMultiSrcGetValuesHook(Widget, ArgList, Cardinal*); 98 99/* 100 * Prototypes 101 */ 102static MultiPiece *AllocNewPiece(MultiSrcObject, MultiPiece*); 103static void BreakPiece(MultiSrcObject, MultiPiece*); 104static Boolean CvtMultiTypeToString(Display*, XrmValuePtr, Cardinal*, 105 XrmValuePtr, XrmValuePtr, XtPointer*); 106static void CvtStringToMultiType(XrmValuePtr, Cardinal*, 107 XrmValuePtr, XrmValuePtr); 108static MultiPiece *FindPiece(MultiSrcObject, XawTextPosition, 109 XawTextPosition*); 110static void FreeAllPieces(MultiSrcObject); 111static FILE *InitStringOrFile(MultiSrcObject, Bool); 112static void LoadPieces(MultiSrcObject, FILE*, char*); 113static void RemovePiece(MultiSrcObject, MultiPiece*); 114static void RemoveOldStringOrFile(MultiSrcObject, Bool); 115static String StorePiecesInString(MultiSrcObject); 116static Bool WriteToFile(String, String); 117static void GetDefaultPieceSize(Widget, int, XrmValue*); 118 119/* 120 * Initialization 121 */ 122#define offset(field) XtOffsetOf(MultiSrcRec, multi_src.field) 123static XtResource resources[] = { 124 { 125 XtNstring, 126 XtCString, 127 XtRString, 128 sizeof(XtPointer), 129 offset(string), 130 XtRPointer, 131 NULL 132 }, 133 { 134 XtNtype, 135 XtCType, 136 XtRMultiType, 137 sizeof(XawAsciiType), 138 offset(type), 139 XtRImmediate, 140 (XtPointer)XawAsciiString 141 }, 142 { 143 XtNdataCompression, 144 XtCDataCompression, 145 XtRBoolean, 146 sizeof(Boolean), 147 offset(data_compression), 148 XtRImmediate, 149 (XtPointer)False 150 }, 151 { 152 XtNpieceSize, 153 XtCPieceSize, 154 XtRInt, 155 sizeof(XawTextPosition), 156 offset(piece_size), 157 XtRCallProc, 158 (XtPointer)GetDefaultPieceSize 159 }, 160#ifdef OLDXAW 161 { 162 XtNcallback, 163 XtCCallback, 164 XtRCallback, 165 sizeof(XtPointer), 166 offset(callback), 167 XtRCallback, 168 (XtPointer)NULL 169 }, 170#endif 171 { 172 XtNuseStringInPlace, 173 XtCUseStringInPlace, 174 XtRBoolean, 175 sizeof(Boolean), 176 offset(use_string_in_place), 177 XtRImmediate, 178 (XtPointer)False 179 }, 180 { 181 XtNlength, 182 XtCLength, 183 XtRInt, 184 sizeof(int), 185 offset(multi_length), 186 XtRImmediate, 187 (XtPointer)MAGIC_VALUE 188 }, 189}; 190#undef offset 191 192#define superclass (&textSrcClassRec) 193MultiSrcClassRec multiSrcClassRec = { 194 /* object */ 195 { 196 (WidgetClass)superclass, /* superclass */ 197 "MultiSrc", /* class_name */ 198 sizeof(MultiSrcRec), /* widget_size */ 199 XawMultiSrcClassInitialize, /* class_initialize */ 200 NULL, /* class_part_initialize */ 201 False, /* class_inited */ 202 XawMultiSrcInitialize, /* initialize */ 203 NULL, /* initialize_hook */ 204 NULL, /* obj1 */ 205 NULL, /* obj2 */ 206 0, /* obj3 */ 207 resources, /* resources */ 208 XtNumber(resources), /* num_resources */ 209 NULLQUARK, /* xrm_class */ 210 False, /* obj4 */ 211 False, /* obj5 */ 212 False, /* obj6 */ 213 False, /* obj7 */ 214 XawMultiSrcDestroy, /* destroy */ 215 NULL, /* obj8 */ 216 NULL, /* obj9 */ 217 XawMultiSrcSetValues, /* set_values */ 218 NULL, /* set_values_hook */ 219 NULL, /* obj10 */ 220 XawMultiSrcGetValuesHook, /* get_values_hook */ 221 NULL, /* obj11 */ 222 XtVersion, /* version */ 223 NULL, /* callback_private */ 224 NULL, /* obj12 */ 225 NULL, /* obj13 */ 226 NULL, /* obj14 */ 227 NULL, /* extension */ 228 }, 229 /* text_src */ 230 { 231 ReadText, /* Read */ 232 ReplaceText, /* Replace */ 233 Scan, /* Scan */ 234 Search, /* Search */ 235 XtInheritSetSelection, /* SetSelection */ 236 XtInheritConvertSelection, /* ConvertSelection */ 237 }, 238 /* multi_src */ 239 { 240 NULL, /* extension */ 241 }, 242}; 243 244WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec; 245 246static XrmQuark Qstring, Qfile; 247 248/* 249 * Implementation 250 */ 251static void 252XawMultiSrcClassInitialize(void) 253{ 254 XawInitializeWidgetSet(); 255 Qstring = XrmPermStringToQuark(XtEstring); 256 Qfile = XrmPermStringToQuark(XtEfile); 257 XtAddConverter(XtRString, XtRMultiType, CvtStringToMultiType, NULL, 0); 258 XtSetTypeConverter(XtRMultiType, XtRString, CvtMultiTypeToString, NULL, 0, 259 XtCacheNone, NULL); 260} 261 262/* 263 * Function: 264 * XawMultiSrcInitialize 265 * 266 * Parameters: 267 * request - widget requested by the argument list 268 * cnew - the new widget with both resource and non resource values 269 * args - (unused) 270 * num_args - (unused) 271 * 272 * Description: 273 * Initializes the multi src object 274 */ 275/*ARGSUSED*/ 276static void 277XawMultiSrcInitialize(Widget request, Widget cnew, 278 ArgList args, Cardinal *num_args) 279{ 280 MultiSrcObject src = (MultiSrcObject)cnew; 281 FILE *file; 282 283 /* 284 * Set correct flags (override resources) depending upon widget class 285 */ 286#ifdef OLDXAW 287 src->multi_src.changes = False; 288#else 289 src->text_src.changed = False; 290#endif 291 src->multi_src.allocated_string = False; 292 293 if (src->multi_src.use_string_in_place && src->multi_src.string == NULL) 294 src->multi_src.use_string_in_place = False; 295 296 file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile); 297 LoadPieces(src, file, NULL); 298 299 if (file != NULL) 300 fclose(file); 301 src->text_src.text_format = XawFmtWide; 302} 303 304/* 305 * Function: 306 * ReadText 307 * 308 * Parameters: 309 * w - MultiSource object 310 * pos - position of the text to retrieve 311 * text - text block that will contain returned text 312 * length - maximum number of characters to read 313 * 314 * Description: 315 * This function reads the source. 316 * 317 * Returns: 318 * The character position following the retrieved text. 319 */ 320static XawTextPosition 321ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length) 322{ 323 MultiSrcObject src = (MultiSrcObject)w; 324 XawTextPosition count, start; 325 MultiPiece *piece = FindPiece(src, pos, &start); 326 327 text->format = XawFmtWide; 328 text->firstPos = pos; 329 text->ptr = (char *)(piece->text + (pos - start)); 330 count = piece->used - (pos - start); 331 text->length = Max(0, (length > count) ? count : length); 332 333 return (pos + text->length); 334} 335 336/* 337 * Function: 338 * ReplaceText 339 * 340 * Parameters: 341 * w - MultiSource object 342 * startPos - ends of text that will be removed 343 * endPos - "" 344 * text - new text to be inserted into buffer at startPos 345 * 346 * Description: 347 * Replaces a block of text with new text. 348 * 349 * Returns: 350 * XawEditDone on success, XawEditError otherwise 351 */ 352/*ARGSUSED*/ 353static int 354ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos, 355 XawTextBlock *u_text_p) 356{ 357 MultiSrcObject src = (MultiSrcObject)w; 358 MultiPiece *start_piece, *end_piece, *temp_piece; 359 XawTextPosition start_first, end_first; 360 int length, firstPos; 361 wchar_t *wptr; 362 Bool local_artificial_block = False; 363 XawTextBlock text; 364 365 /* STEP 1: The user handed me a text block called `u_text' that may be 366 * in either FMTWIDE or FMT8BIT (ie MB.) Later code needs the block 367 * `text' to hold FMTWIDE. So, this copies `u_text' to `text', and if 368 * `u_text' was MB, I knock it up to WIDE 369 */ 370 if (u_text_p->length == 0) /* if so, the block contents never ref'd */ 371 text.length = 0; 372 373 else if (u_text_p->format == XawFmtWide) { 374 local_artificial_block = False; /* don't have to free it ourselves */ 375 text.firstPos = u_text_p->firstPos; 376 text.length = u_text_p->length; 377 text.ptr = u_text_p->ptr; 378 } 379 else { 380 /* 381 * WARNING! u_text->firstPos and length are in units of CHAR, 382 * not CHARACTERS! 383 */ 384 local_artificial_block = True; /* have to free it ourselves */ 385 text.firstPos = 0; 386 text.length = u_text_p->length; /* _XawTextMBToWC converts this 387 * to wchar len 388 */ 389 390 text.ptr = (char*)_XawTextMBToWC(XtDisplay(XtParent(w)), 391 &u_text_p->ptr[u_text_p->firstPos], 392 &text.length); 393 394 /* I assert the following assignment is not needed - since Step 4 395 depends on length, it has no need of a terminating NULL. I think 396 the ASCII-version has the same needless NULL. */ 397 /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/ 398 } 399 400 /* STEP 2: some initialization... */ 401 if (src->text_src.edit_mode == XawtextRead) 402 return (XawEditError); 403 404 start_piece = FindPiece(src, startPos, &start_first); 405 end_piece = FindPiece(src, endPos, &end_first); 406 407 /* STEP 3: remove the empty pieces... */ 408 if (start_piece != end_piece) { 409 temp_piece = start_piece->next; 410 411 /* If empty and not the only piece then remove it */ 412 if (((start_piece->used = startPos - start_first) == 0) 413 && !(start_piece->next == NULL && start_piece->prev == NULL)) 414 RemovePiece(src, start_piece); 415 416 while (temp_piece != end_piece) { 417 temp_piece = temp_piece->next; 418 RemovePiece(src, temp_piece->prev); 419 } 420 end_piece->used -= endPos - end_first; 421 if (end_piece->used != 0) 422 memmove(end_piece->text, end_piece->text + endPos - end_first, 423 end_piece->used * sizeof(wchar_t)); 424 } 425 else { /* We are fully in one piece */ 426 if ((start_piece->used -= endPos - startPos) == 0) { 427 if (!(start_piece->next == NULL && start_piece->prev == NULL)) 428 RemovePiece(src, start_piece); 429 } 430 else { 431 memmove(start_piece->text + (startPos - start_first), 432 start_piece->text + (endPos - start_first), 433 (start_piece->used - (startPos - start_first)) * 434 sizeof(wchar_t)); 435 if (src->multi_src.use_string_in_place && 436 ((src->multi_src.length - (endPos - startPos)) 437 < src->multi_src.piece_size - 1)) 438 start_piece->text[src->multi_src.length - (endPos - startPos)] = 439 (wchar_t)0; 440 } 441 } 442 443 src->multi_src.length += text.length -(endPos - startPos); 444 445 /* STEP 4: insert the new stuff */ 446 if ( text.length != 0) { 447 start_piece = FindPiece(src, startPos, &start_first); 448 length = text.length; 449 firstPos = text.firstPos; 450 451 while (length > 0) { 452 wchar_t *ptr; 453 int fill; 454 455 if (src->multi_src.use_string_in_place) { 456 if (start_piece->used == src->multi_src.piece_size - 1) { 457 458 /* 459 * The string is used in place, then the string 460 * is not allowed to grow 461 */ 462 start_piece->used = src->multi_src.length = 463 src->multi_src.piece_size - 1; 464 465 start_piece->text[src->multi_src.length] = (wchar_t)0; 466 return (XawEditError); 467 } 468 } 469 470 if (start_piece->used == src->multi_src.piece_size) { 471 BreakPiece(src, start_piece); 472 start_piece = FindPiece(src, startPos, &start_first); 473 } 474 475 fill = Min((int)(src->multi_src.piece_size - start_piece->used), length); 476 477 ptr = start_piece->text + (startPos - start_first); 478 memmove(ptr + fill, ptr, (start_piece->used - 479 (startPos - start_first)) * sizeof(wchar_t)); 480 wptr =(wchar_t *)text.ptr; 481 (void)wcsncpy(ptr, wptr + firstPos, fill); 482 483 startPos += fill; 484 firstPos += fill; 485 start_piece->used += fill; 486 length -= fill; 487 } 488 } 489 490 if (local_artificial_block == True) 491 /* In other words, text is not the u_text that the user handed me but 492 one I made myself. I only care, because I need to free the string */ 493 XtFree(text.ptr); 494 495 if (src->multi_src.use_string_in_place) 496 start_piece->text[start_piece->used] = (wchar_t)0; 497 498#ifdef OLDXAW 499 src->multi_src.changes = True; 500 XtCallCallbacks(w, XtNcallback, NULL); 501#endif 502 503 return (XawEditDone); 504} 505 506/* 507 * Function: 508 * Scan 509 * 510 * Parameters: 511 * w - MultiSource widget 512 * position - position to start scanning 513 * type - type of thing to scan for 514 * dir - direction to scan 515 * count - which occurance if this thing to search for 516 * include - whether or not to include the character found in 517 * the position that is returned 518 * 519 * Description: 520 * Scans the text source for the number and type of item specified. 521 * 522 * Returns: 523 * The position of the item found 524 * 525 * Note: 526 * While there are only 'n' characters in the file there are n+1 527 * possible cursor positions (one before the first character and 528 * one after the last character 529 */ 530static XawTextPosition 531Scan(Widget w, register XawTextPosition position, XawTextScanType type, 532 XawTextScanDirection dir, int count, Bool include) 533{ 534 MultiSrcObject src = (MultiSrcObject)w; 535 register char inc; 536 MultiPiece *piece; 537 XawTextPosition first, first_eol_position = position; 538 register wchar_t *ptr; 539 int cnt = count; 540 541 if (type == XawstAll) { 542 if (dir == XawsdRight) 543 return (src->multi_src.length); 544 return (0); 545 } 546 547 /* STEP 1: basic sanity checks */ 548 if (position > src->multi_src.length) 549 position = src->multi_src.length; 550 551 if (dir == XawsdRight) { 552 if (position == src->multi_src.length) 553 return (src->multi_src.length); 554 inc = 1; 555 } 556 else { 557 if (position == 0) 558 return (0); 559 inc = -1; 560 position--; 561 } 562 563 piece = FindPiece(src, position, &first); 564 565 if (piece->used == 0) 566 return (0); 567 568 ptr = (position - first) + piece->text; 569 570 switch (type) { 571 case XawstEOL: 572 case XawstParagraph: 573 case XawstWhiteSpace: 574 case XawstAlphaNumeric: 575 for (; cnt > 0 ; cnt--) { 576 Bool non_space = False, first_eol = True; 577 578 /*CONSTCOND*/ 579 while (True) { 580 register wchar_t c; 581 582 if (ptr < piece->text) { 583 piece = piece->prev; 584 if (piece == NULL) /* Begining of text */ 585 return (0); 586 ptr = piece->text + piece->used - 1; 587 c = *ptr; 588 } 589 else if (ptr >= piece->text + piece->used) { 590 piece = piece->next; 591 if (piece == NULL) /* End of text */ 592 return (src->multi_src.length); 593 ptr = piece->text; 594 } 595 596 c = *ptr; 597 ptr += inc; 598 position += inc; 599 600 if (type == XawstAlphaNumeric) { 601 if (!iswalnum(c)) { 602 if (non_space) 603 break; 604 } 605 else 606 non_space = True; 607 } 608 else if (type == XawstWhiteSpace) { 609 if (iswspace(c)) { 610 if (non_space) 611 break; 612 } 613 else 614 non_space = True; 615 } 616 else if (type == XawstEOL) { 617 if (c == _Xaw_atowc(XawLF)) 618 break; 619 } 620 else { /* XawstParagraph */ 621 if (first_eol) { 622 if (c == _Xaw_atowc(XawLF)) { 623 first_eol_position = position; 624 first_eol = False; 625 } 626 } 627 else 628 if (c == _Xaw_atowc(XawLF)) 629 break; 630 else if (!iswspace(c)) 631 first_eol = True; 632 } 633 } 634 } 635 if (!include) { 636 if (type == XawstParagraph) 637 position = first_eol_position; 638 if (count) 639 position -= inc; 640 } 641 break; 642 case XawstPositions: 643 position += count * inc; 644 break; 645 default: 646 break; 647 } 648 649 if (dir == XawsdLeft) 650 position++; 651 652 if (position >= src->multi_src.length) 653 return (src->multi_src.length); 654 if (position < 0) 655 return (0); 656 657 return (position); 658} 659 660/* 661 * Function: 662 * Search 663 * 664 * Parameters: 665 * w - MultiSource objecy 666 * position - position to start scanning 667 * dir - direction to scan 668 * text - text block to search for 669 * 670 * Description: 671 * Searchs the text source for the text block passed. 672 * 673 * Returns: 674 * The position of the item found 675 */ 676static XawTextPosition 677Search(Widget w, register XawTextPosition position, XawTextScanDirection dir, 678 XawTextBlock *text) 679{ 680 MultiSrcObject src = (MultiSrcObject)w; 681 register int count = 0; 682 wchar_t *ptr; 683 wchar_t *wtarget; 684 int wtarget_len; 685 Display *d = XtDisplay(XtParent(w)); 686 MultiPiece *piece; 687 wchar_t *buf; 688 XawTextPosition first; 689 register char inc; 690 int cnt; 691 692 /* STEP 1: First, a brief sanity check */ 693 if (dir == XawsdRight) 694 inc = 1; 695 else { 696 inc = -1; 697 if (position == 0) 698 return (XawTextSearchError); 699 position--; 700 } 701 702 /* STEP 2: Ensure I have a local wide string.. */ 703 704 /* Since this widget stores 32bit chars, I check here to see if 705 I'm being passed a string claiming to be 8bit chars (ie, MB text.) 706 If that is the case, naturally I convert to 32bit format */ 707 708 /*if the block was FMT8BIT, length will convert to REAL wchar count bellow */ 709 wtarget_len = text->length; 710 711 if (text->format == XawFmtWide) 712 wtarget = &(((wchar_t*)text->ptr) [text->firstPos]); 713 else { 714 /* The following converts wtarget_len from byte len to wchar count */ 715 wtarget = _XawTextMBToWC(d, &text->ptr[text->firstPos], &wtarget_len); 716 } 717 718 /* OK, I can now assert that wtarget holds wide characters, wtarget_len 719 holds an accurate count of those characters, and that firstPos has been 720 effectively factored out of the following computations */ 721 722 /* STEP 3: SEARCH! */ 723 buf = (wchar_t *)XtMalloc(sizeof(wchar_t) * wtarget_len); 724 (void)wcsncpy(buf, wtarget, wtarget_len); 725 piece = FindPiece(src, position, &first); 726 ptr = (position - first) + piece->text; 727 728 /*CONSTCOND*/ 729 while (True) { 730 if (*ptr == (dir == XawsdRight ? *(buf + count) 731 : *(buf + wtarget_len - count - 1))) { 732 if (count == text->length - 1) 733 break; 734 else 735 count++; 736 } 737 else { 738 if (count != 0) { 739 position -=inc * count; 740 ptr -= inc * count; 741 } 742 count = 0; 743 } 744 745 ptr += inc; 746 position += inc; 747 748 while (ptr < piece->text) { 749 cnt = piece->text - ptr; 750 751 piece = piece->prev; 752 if (piece == NULL) { /* Begining of text */ 753 XtFree((char *)buf); 754 return (XawTextSearchError); 755 } 756 ptr = piece->text + piece->used - cnt; 757 } 758 759 while (ptr >= piece->text + piece->used) { 760 cnt = ptr - (piece->text + piece->used); 761 762 piece = piece->next; 763 if (piece == NULL) { /* End of text */ 764 XtFree((char *)buf); 765 return (XawTextSearchError); 766 } 767 ptr = piece->text + cnt; 768 } 769 } 770 771 XtFree((char *)buf); 772 if (dir == XawsdLeft) 773 return(position); 774 775 return(position - (wtarget_len - 1)); 776} 777 778/* 779 * Function: 780 * XawMultiSrcSetValues 781 * 782 * Parameters: 783 * current - current state of the widget 784 * request - what was requested 785 * cnew - what the widget will become 786 * args - representation of resources that have changed 787 * num_args - number of changed resources 788 * 789 * Description: 790 * Sets the values for the MultiSource. 791 * 792 * Returns: 793 * True if redisplay is needed 794 */ 795static Boolean 796XawMultiSrcSetValues(Widget current, Widget request, Widget cnew, 797 ArgList args, Cardinal *num_args) 798{ 799 MultiSrcObject src = (MultiSrcObject)cnew; 800 MultiSrcObject old_src = (MultiSrcObject)current; 801 XtAppContext app_con = XtWidgetToApplicationContext(cnew); 802 Bool total_reset = False, string_set = False; 803 FILE *file; 804 unsigned int i; 805 806 if (old_src->multi_src.use_string_in_place 807 != src->multi_src.use_string_in_place) { 808 XtAppWarning(app_con, 809 "MultiSrc: The XtNuseStringInPlace resources " 810 "may not be changed."); 811 src->multi_src.use_string_in_place = 812 old_src->multi_src.use_string_in_place; 813 } 814 815 for (i = 0; i < *num_args ; i++) 816 if (streq(args[i].name, XtNstring)) { 817 string_set = True; 818 break; 819 } 820 821 if (string_set || old_src->multi_src.type != src->multi_src.type) { 822 RemoveOldStringOrFile(old_src, string_set); 823 src->multi_src.allocated_string = old_src->multi_src.allocated_string; 824 file = InitStringOrFile(src, string_set); 825 826 LoadPieces(src, file, NULL); 827 if (file != NULL) 828 fclose(file); 829#ifndef OLDXAW 830 for (i = 0; i < src->text_src.num_text; i++) 831 /* Tell text widget what happened */ 832 XawTextSetSource(src->text_src.text[i], cnew, 0); 833#else 834 XawTextSetSource(XtParent(cnew), cnew, 0); 835#endif 836 total_reset = True; 837 } 838 839 if (old_src->multi_src.multi_length != src->multi_src.multi_length) 840 src->multi_src.piece_size = src->multi_src.multi_length + 1; 841 842 if ( !total_reset && old_src->multi_src.piece_size 843 != src->multi_src.piece_size) { 844 String mb_string = StorePiecesInString(old_src); 845 846 if (mb_string != 0) { 847 FreeAllPieces(old_src); 848 LoadPieces(src, NULL, mb_string); 849 XtFree(mb_string); 850 } 851 else { 852 /* If the buffer holds bad chars, don't touch it... */ 853 XtAppWarningMsg(app_con, 854 "convertError", "multiSource", "XawError", 855 XtName(XtParent((Widget)old_src)), NULL, NULL); 856 XtAppWarningMsg(app_con, 857 "convertError", "multiSource", "XawError", 858 "Non-character code(s) in buffer.", NULL, NULL); 859 } 860 } 861 862 return (False); 863} 864 865static void 866XawMultiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args) 867{ 868 MultiSrcObject src = (MultiSrcObject)w; 869 unsigned int i; 870 871 if (src->multi_src.type == XawAsciiString) { 872 for (i = 0; i < *num_args ; i++) { 873 if (streq(args[i].name, XtNstring)) { 874 if (src->multi_src.use_string_in_place) 875 *((char **)args[i].value) = (char *) 876 src->multi_src.first_piece->text; 877 else if (_XawMultiSave(w)) /* If save sucessful */ 878 *((char **)args[i].value) = (char *)src->multi_src.string; 879 break; 880 } 881 } 882 } 883} 884 885static void 886XawMultiSrcDestroy(Widget w) 887{ 888 RemoveOldStringOrFile((MultiSrcObject) w, True); 889} 890 891/* 892 * Public routines 893 */ 894/* 895 * Function: 896 * XawMultiSourceFreeString 897 * 898 * Parameters: 899 * w - MultiSrc widget 900 * 901 * Description: 902 * Frees the string returned by a get values call 903 * on the string when the source is of type string. 904 * 905 * Note: 906 * The public interface is XawAsciiSourceFreeString! 907 */ 908void 909_XawMultiSourceFreeString(Widget w) 910{ 911 MultiSrcObject src = (MultiSrcObject)w; 912 913 if (src->multi_src.allocated_string) { 914 XtFree((char *)src->multi_src.string); 915 src->multi_src.allocated_string = False; 916 src->multi_src.string = NULL; 917 } 918} 919 920/* 921 * Function: 922 * _XawMultiSave 923 * 924 * Parameters: 925 * w - multiSrc Widget 926 * 927 * Description: 928 * Saves all the pieces into a file or string as required. 929 * 930 * Returns: 931 * True if the save was successful 932 * 933 * Note: 934 * The public interface is XawAsciiSave(w)! 935 */ 936Bool 937_XawMultiSave(Widget w) 938{ 939 MultiSrcObject src = (MultiSrcObject)w; 940 XtAppContext app_con = XtWidgetToApplicationContext(w); 941 char *mb_string; 942 943 /* 944 * If using the string in place then there is no need to play games 945 * to get the internal info into a readable string 946 */ 947 if (src->multi_src.use_string_in_place) 948 return (True); 949 950 if (src->multi_src.type == XawAsciiFile) { 951#ifdef OLDXAW 952 if (!src->multi_src.changes) 953#else 954 if (!src->text_src.changed) /* No changes to save */ 955#endif 956 return (True); 957 958 mb_string = StorePiecesInString(src); 959 960 if (mb_string != 0) { 961 if (WriteToFile(mb_string, (String)src->multi_src.string) == False) { 962 XtFree(mb_string); 963 return (False); 964 } 965 XtFree(mb_string); 966#ifndef OLDXAW 967 src->text_src.changed = False; 968#else 969 src->multi_src.changes = False; 970#endif 971 return (True); 972 } 973 else { 974 /* If the buffer holds bad chars, don't touch it... */ 975 XtAppWarningMsg(app_con, 976 "convertError", "multiSource", "XawError", 977 "Due to illegal characters, file not saved.", 978 NULL, NULL); 979 return (False); 980 } 981 } 982 else { 983 /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED? The manual 984 says this routine's only function is to save files to 985 disk. -Sheeran */ 986 mb_string = StorePiecesInString(src); 987 988 if (mb_string == 0) { 989 /* If the buffer holds bad chars, don't touch it... */ 990 XtAppWarningMsg(app_con, 991 "convertError", "multiSource", "XawError", 992 XtName(XtParent((Widget)src)), NULL, NULL); 993 return (False); 994 } 995 996 /* assert: mb_string holds good characters so the buffer is fine */ 997 if (src->multi_src.allocated_string == True) 998 XtFree((char *)src->multi_src.string); 999 else 1000 src->multi_src.allocated_string = True; 1001 1002 src->multi_src.string = mb_string; 1003 } 1004#ifdef OLDXAW 1005 src->multi_src.changes = False; 1006#else 1007 src->text_src.changed = False; 1008#endif 1009 1010 return (True); 1011} 1012 1013/* 1014 * Function: 1015 * XawMultiSaveAsFile 1016 * 1017 * Parameters: 1018 * w - MultiSrc widget 1019 * name - name of the file to save this file into 1020 * 1021 * Description: 1022 * Save the current buffer as a file. 1023 * 1024 * Returns: 1025 * True if the save was sucessful 1026 * 1027 * Note: 1028 * The public interface is XawAsciiSaveAsFile! 1029 */ 1030Bool 1031_XawMultiSaveAsFile(Widget w, _Xconst char* name) 1032{ 1033 MultiSrcObject src = (MultiSrcObject)w; 1034 String mb_string; 1035 Bool ret; 1036 1037 mb_string = StorePiecesInString(src); 1038 1039 if (mb_string != 0) { 1040 ret = WriteToFile(mb_string, (char *)name); 1041 XtFree(mb_string); 1042 1043 return (ret); 1044 } 1045 1046 /* otherwise there was a conversion error. So print widget name too */ 1047 XtAppWarningMsg(XtWidgetToApplicationContext(w), 1048 "convertError", "multiSource", "XawError", 1049 XtName(XtParent(w)), NULL, NULL); 1050 1051 return (False); 1052} 1053 1054/* 1055 * Private Functions 1056 */ 1057static void 1058RemoveOldStringOrFile(MultiSrcObject src, Bool checkString) 1059{ 1060 FreeAllPieces(src); 1061 1062 if (checkString && src->multi_src.allocated_string) { 1063 XtFree((char *)src->multi_src.string); 1064 src->multi_src.allocated_string = False; 1065 src->multi_src.string = NULL; 1066 } 1067} 1068 1069/* 1070 * Function: 1071 * WriteToFile 1072 * 1073 * Parameters: 1074 * string - string to write 1075 * name - name of the file 1076 * 1077 * Description: 1078 * Write the string specified to the begining of the file specified. 1079 * 1080 * Returns: 1081 * Returns True if sucessful, False otherwise 1082 */ 1083static Bool 1084WriteToFile(String string, String name) 1085{ 1086 int fd; 1087 Bool result = True; 1088 1089 if ((fd = creat(name, 0666)) == -1) 1090 return (False); 1091 1092 if (write(fd, string, strlen(string)) == -1) 1093 result = False; 1094 1095 if (close(fd) == -1) 1096 return (False); 1097 1098 return (result); 1099} 1100 1101 1102/* 1103 * Function: 1104 * StorePiecesInString 1105 * 1106 * Parameters: 1107 * src - the multiSrc object to gather data from 1108 * 1109 * Description: 1110 * Store the pieces in memory into a char string. 1111 * 1112 * Returns: 1113 * mb_string: Caller must free 1114 * (or) 1115 * NULL: conversion error 1116 */ 1117static String 1118StorePiecesInString(MultiSrcObject src) 1119{ 1120 wchar_t *wc_string; 1121 char *mb_string; 1122 int char_count = src->multi_src.length; 1123 XawTextPosition first; 1124 MultiPiece *piece; 1125 1126 /* I believe the char_count + 1 and the NULL termination are unneeded! FS */ 1127 wc_string = (wchar_t*)XtMalloc((char_count + 1) * sizeof(wchar_t)); 1128 1129 for (first = 0, piece = src->multi_src.first_piece ; piece != NULL; 1130 first += piece->used, piece = piece->next) 1131 (void)wcsncpy(wc_string + first, piece->text, piece->used); 1132 1133 wc_string[char_count] = 0; 1134 1135 /* This will refill all pieces to capacity */ 1136 if (src->multi_src.data_compression) { 1137 FreeAllPieces(src); 1138 LoadPieces(src, NULL, (char *)wc_string); 1139 } 1140 1141 /* Lastly, convert it to a MB format and send it back */ 1142 mb_string = _XawTextWCToMB(XtDisplayOfObject((Widget)src), 1143 wc_string, &char_count); 1144 1145 /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED */ 1146 XtFree((char*)wc_string); 1147 1148 return (mb_string); 1149} 1150 1151/* 1152 * Function: 1153 * InitStringOrFile 1154 * 1155 * Parameters: 1156 * src - MultiSource 1157 * 1158 * Description: 1159 * Initializes the string or file. 1160 */ 1161static FILE * 1162InitStringOrFile(MultiSrcObject src, Bool newString) 1163{ 1164 mode_t open_mode = 0; 1165 const char *fdopen_mode = NULL; 1166 int fd; 1167 FILE *file; 1168 Display *d = XtDisplayOfObject((Widget)src); 1169 1170 if (src->multi_src.type == XawAsciiString) { 1171 if (src->multi_src.string == NULL) 1172 src->multi_src.length = 0; 1173 1174 else if (!src->multi_src.use_string_in_place) { 1175 int length; 1176 String temp = XtNewString((char *)src->multi_src.string); 1177 1178 if (src->multi_src.allocated_string) 1179 XtFree((char *)src->multi_src.string); 1180 src->multi_src.allocated_string = True; 1181 src->multi_src.string = temp; 1182 1183 length = strlen((char *)src->multi_src.string); 1184 1185 /* Wasteful, throwing away the WC string, but need side effect! */ 1186 (void)_XawTextMBToWC(d, (char *)src->multi_src.string, &length); 1187 src->multi_src.length = (XawTextPosition)length; 1188 } 1189 else { 1190 src->multi_src.length = strlen((char *)src->multi_src.string); 1191 /* In case the length resource is incorrectly set */ 1192 if (src->multi_src.length > src->multi_src.multi_length) 1193 src->multi_src.multi_length = src->multi_src.length; 1194 1195 if (src->multi_src.multi_length == MAGIC_VALUE) 1196 src->multi_src.piece_size = src->multi_src.length; 1197 else 1198 src->multi_src.piece_size = src->multi_src.multi_length + 1; 1199 } 1200 1201 return (NULL); 1202 } 1203 1204 /* 1205 * type is XawAsciiFile 1206 */ 1207 src->multi_src.is_tempfile = False; 1208 1209 switch (src->text_src.edit_mode) { 1210 case XawtextRead: 1211 if (src->multi_src.string == NULL) 1212 XtErrorMsg("NoFile", "multiSourceCreate", "XawError", 1213 "Creating a read only disk widget and no file specified.", 1214 NULL, 0); 1215 open_mode = O_RDONLY; 1216 fdopen_mode = "r"; 1217 break; 1218 case XawtextAppend: 1219 case XawtextEdit: 1220 if (src->multi_src.string == NULL) { 1221 src->multi_src.string = "*multi-src*"; 1222 src->multi_src.is_tempfile = True; 1223 } 1224 else { 1225/* O_NOFOLLOW is a BSD & Linux extension */ 1226#ifdef O_NOFOLLOW 1227 open_mode = O_RDWR | O_NOFOLLOW; 1228#else 1229 open_mode = O_RDWR; /* unsafe; subject to race conditions */ 1230#endif 1231 fdopen_mode = "r+"; 1232 } 1233 break; 1234 default: 1235 XtErrorMsg("badMode", "multiSourceCreate", "XawError", 1236 "Bad editMode for multi source; must be " 1237 "Read, Append or Edit.", NULL, NULL); 1238 } 1239 1240 /* If is_tempfile, allocate a private copy of the text 1241 * Unlikely to be changed, just to set allocated_string */ 1242 if (newString || src->multi_src.is_tempfile) { 1243 String temp = XtNewString((char *)src->multi_src.string); 1244 1245 if (src->multi_src.allocated_string) 1246 XtFree((char *)src->multi_src.string); 1247 src->multi_src.string = temp; 1248 src->multi_src.allocated_string = True; 1249 } 1250 1251 if (!src->multi_src.is_tempfile) { 1252 if ((fd = open((char *)src->multi_src.string, open_mode, 0666)) != -1) { 1253 if ((file = fdopen(fd, fdopen_mode)) != NULL) { 1254 (void)fseek(file, 0, SEEK_END); 1255 src->multi_src.length = (XawTextPosition)ftell(file); 1256 return(file); 1257 } 1258 else 1259 close(fd); 1260 } 1261 { 1262 String params[2]; 1263 Cardinal num_params = 2; 1264 1265 params[0] = (String)src->multi_src.string; 1266 params[1] = strerror(errno); 1267 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), 1268 "openError", "multiSourceCreate", "XawWarning", 1269 "Cannot open file %s; %s", params, &num_params); 1270 } 1271 } 1272 src->multi_src.length = 0; 1273 return (NULL); 1274} 1275 1276/* LoadPieces: This routine takes either the MB contents of open file 1277 `file' or the MB contents of string or the MB contents of 1278 src->multi_src.string and places them in Pieces in WC format. 1279 1280 CAUTION: You must have src->multi_src.length set to file length bytes 1281 when src->multi_src.type == XawAsciiFile. src->multi_src.length must be 1282 the length of the parameter string if string is non-NULL 1283*/ 1284static void 1285LoadPieces(MultiSrcObject src, FILE *file, char *string) 1286{ 1287 Display *d = XtDisplayOfObject((Widget)src); 1288 wchar_t* local_str, *ptr; 1289 MultiPiece* piece = NULL; 1290 XawTextPosition left; 1291 int bytes = sizeof(wchar_t); 1292 char* temp_mb_holder = NULL; 1293 1294 /* 1295 * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg 1296 * in as MB length, out as WC length. We want local_length to be 1297 * WC count. 1298 */ 1299 int local_length = src->multi_src.length; 1300 1301 if (string != NULL) { 1302 /* 1303 * ASSERT: IF our caller passed a non-null string, THEN 1304 * src->multi_src.length is currently string's * byte count, 1305 * AND string is in a MB format 1306 */ 1307 local_str = _XawTextMBToWC(d, (char *)string, &local_length); 1308 src->multi_src.length = (XawTextPosition) local_length; 1309 } 1310 else if (src->multi_src.type != XawAsciiFile) { 1311 /* 1312 * here, we are not changing the contents, just reloading, 1313 * so don't change len... 1314 */ 1315 local_length = src->multi_src.string ? 1316 strlen((char *)src->multi_src.string) : 0; 1317 local_str = _XawTextMBToWC(d, (char *)src->multi_src.string, 1318 &local_length); 1319 } 1320 else { 1321 if (src->multi_src.length != 0) { 1322 temp_mb_holder = 1323 XtMalloc((src->multi_src.length + 1) * sizeof(unsigned char)); 1324 fseek(file, 0, SEEK_SET); 1325 src->multi_src.length = fread(temp_mb_holder, 1326 sizeof(unsigned char), 1327 (size_t)src->multi_src.length, file); 1328 if (src->multi_src.length <= 0) 1329 XtAppErrorMsg(XtWidgetToApplicationContext ((Widget) src), 1330 "readError", "multiSource", "XawError", 1331 "fread returned error.", NULL, NULL); 1332 local_length = src->multi_src.length; 1333 local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length); 1334 src->multi_src.length = local_length; 1335 1336 if (local_str == 0) { 1337 String params[2]; 1338 Cardinal num_params; 1339 static char err_text[] = 1340 "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>"; 1341 1342 params[0] = XtName(XtParent((Widget)src)); 1343 params[1] = src->multi_src.string; 1344 num_params = 2; 1345 1346 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), 1347 "readLocaleError", "multiSource", "XawError", 1348 "%s: The file `%s' contains characters " 1349 "not representable in this locale.", 1350 params, &num_params); 1351 src->multi_src.length = sizeof err_text; 1352 local_length = src->multi_src.length; 1353 local_str = _XawTextMBToWC(d, err_text, &local_length); 1354 src->multi_src.length = local_length; 1355 } 1356 } 1357 else 1358 /* ASSERT that since following while loop looks at local_length 1359 this isn't needed. Sheeran, Omron KK, 1993/07/15 1360 temp_mb_holder[src->multi_src.length] = '\0'; */ 1361 local_str = (wchar_t*)temp_mb_holder; 1362 } 1363 1364 if (src->multi_src.use_string_in_place) { 1365 piece = AllocNewPiece(src, piece); 1366 piece->used = Min(src->multi_src.length, src->multi_src.piece_size); 1367 piece->text = (wchar_t*)src->multi_src.string; 1368 return; 1369 } 1370 1371 ptr = local_str; 1372 left = local_length; 1373 1374 do { 1375 piece = AllocNewPiece(src, piece); 1376 1377 piece->text = (wchar_t*)XtMalloc((unsigned)(src->multi_src.piece_size 1378 * bytes)); 1379 piece->used = Min(left, src->multi_src.piece_size); 1380 if (piece->used != 0) 1381 (void)wcsncpy(piece->text, ptr, piece->used); 1382 1383 left -= piece->used; 1384 ptr += piece->used; 1385 } while (left > 0); 1386 1387 if (temp_mb_holder) 1388 XtFree((char*)temp_mb_holder); 1389} 1390 1391/* 1392 * Function: 1393 * AllocNewPiece 1394 * 1395 * Parameters: 1396 * src - MultiSrc Widget 1397 * prev - the piece just before this one, or NULL 1398 * 1399 * Description: 1400 * Allocates a new piece of memory. 1401 * 1402 * Returns: 1403 * The allocated piece 1404 */ 1405static MultiPiece * 1406AllocNewPiece(MultiSrcObject src, MultiPiece *prev) 1407{ 1408 MultiPiece *piece = XtNew(MultiPiece); 1409 1410 if (prev == NULL) { 1411 src->multi_src.first_piece = piece; 1412 piece->next = NULL; 1413 } 1414 else { 1415 if (prev->next != NULL) 1416 (prev->next)->prev = piece; 1417 piece->next = prev->next; 1418 prev->next = piece; 1419 } 1420 1421 piece->prev = prev; 1422 1423 return (piece); 1424} 1425 1426/* 1427 * Function: 1428 * FreeAllPieces 1429 * 1430 * Parameters: 1431 * src - MultiSrc Widget 1432 * 1433 * Description: 1434 * Frees all the pieces 1435 */ 1436static void 1437FreeAllPieces(MultiSrcObject src) 1438{ 1439 MultiPiece *next, *first = src->multi_src.first_piece; 1440 1441#ifdef DEBUG 1442 if (first->prev != NULL) 1443 printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n"); 1444#endif 1445 1446 for (; first != NULL ; first = next) { 1447 next = first->next; 1448 RemovePiece(src, first); 1449 } 1450} 1451 1452/* 1453 * Function: 1454 * RemovePiece 1455 * 1456 * Parameters: 1457 * piece - piece to remove 1458 * 1459 * Description: 1460 * Removes a piece from the list. 1461 */ 1462static void 1463RemovePiece(MultiSrcObject src, MultiPiece *piece) 1464{ 1465 if (piece->prev == NULL) 1466 src->multi_src.first_piece = piece->next; 1467 else 1468 piece->prev->next = piece->next; 1469 1470 if (piece->next != NULL) 1471 piece->next->prev = piece->prev; 1472 1473 if (!src->multi_src.use_string_in_place) 1474 XtFree((char *)piece->text); 1475 1476 XtFree((char *)piece); 1477} 1478 1479/* 1480 * Function: 1481 * FindPiece 1482 * 1483 * Parameters: 1484 * src - MultiSrc Widget 1485 * position - position that we are searching for 1486 * first - position of the first character in this piece (return) 1487 * 1488 * Description: 1489 * Finds the piece containing the position indicated. 1490 * 1491 * Returns: 1492 * Piece that contains this position 1493 */ 1494static MultiPiece * 1495FindPiece(MultiSrcObject src, XawTextPosition position, XawTextPosition *first) 1496{ 1497 MultiPiece *old_piece, *piece; 1498 XawTextPosition temp; 1499 1500 for (old_piece = NULL, piece = src->multi_src.first_piece, temp = 0; 1501 piece; old_piece = piece, piece = piece->next) 1502 if ((temp += piece->used) > position) { 1503 *first = temp - piece->used; 1504 return (piece); 1505 } 1506 1507 *first = temp - (old_piece ? old_piece->used : 0); 1508 1509 return (old_piece); /* if we run off the end the return the last piece */ 1510} 1511 1512/* 1513 * Function: 1514 * BreakPiece 1515 * 1516 * Parameters: 1517 * src - MultiSrc Widget 1518 * piece - piece to break 1519 * 1520 * Description: 1521 * Breaks a full piece into two new pieces. 1522 */ 1523#define HALF_PIECE (src->multi_src.piece_size >> 1) 1524static void 1525BreakPiece(MultiSrcObject src, MultiPiece *piece) 1526{ 1527 MultiPiece *cnew = AllocNewPiece(src, piece); 1528 1529 cnew->text = (wchar_t *) 1530 XtMalloc(src->multi_src.piece_size * sizeof(wchar_t)); 1531 (void)wcsncpy(cnew->text, piece->text + HALF_PIECE, 1532 src->multi_src.piece_size - HALF_PIECE); 1533 piece->used = HALF_PIECE; 1534 cnew->used = src->multi_src.piece_size - HALF_PIECE; 1535} 1536 1537/*ARGSUSED*/ 1538static void 1539CvtStringToMultiType(XrmValuePtr args, Cardinal *num_args, 1540 XrmValuePtr fromVal, XrmValuePtr toVal) 1541{ 1542 static XawAsciiType type = XawAsciiString; 1543 XrmQuark q; 1544 char name[7]; 1545 1546 XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); 1547 q = XrmStringToQuark(name); 1548 1549 if (q == Qstring) 1550 type = XawAsciiString; 1551 if (q == Qfile) 1552 type = XawAsciiFile; 1553 else { 1554 toVal->size = 0; 1555 toVal->addr = NULL; 1556 XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType); 1557 } 1558 1559 toVal->size = sizeof(XawAsciiType); 1560 toVal->addr = (XPointer)&type; 1561} 1562 1563/*ARGSUSED*/ 1564static Boolean 1565CvtMultiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, 1566 XrmValuePtr fromVal, XrmValuePtr toVal, 1567 XtPointer *data) 1568{ 1569 static String buffer; 1570 Cardinal size; 1571 1572 switch (*(XawAsciiType *)fromVal->addr) { 1573 case XawAsciiFile: 1574 buffer = XtEfile; 1575 break; 1576 case XawAsciiString: 1577 buffer = XtEstring; 1578 break; 1579 default: 1580 XawTypeToStringWarning(dpy, XtRAsciiType); 1581 toVal->addr = NULL; 1582 toVal->size = 0; 1583 return (False); 1584 } 1585 1586 size = strlen(buffer) + 1; 1587 if (toVal->addr != NULL) { 1588 if (toVal->size < size) { 1589 toVal->size = size; 1590 return (False); 1591 } 1592 strcpy((char *)toVal->addr, buffer); 1593 } 1594 else 1595 toVal->addr = (XPointer)buffer; 1596 toVal->size = sizeof(String); 1597 1598 return (True); 1599} 1600 1601/*ARGSUSED*/ 1602static void 1603GetDefaultPieceSize(Widget w, int offset, XrmValue *value) 1604{ 1605 static XPointer pagesize; 1606 1607 if (pagesize == 0) { 1608 pagesize = (XPointer)((long)_XawGetPageSize()); 1609 if (pagesize < (XPointer)BUFSIZ) 1610 pagesize = (XPointer)BUFSIZ; 1611 } 1612 1613 value->addr = (XPointer)&pagesize; 1614} 1615