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