MultiSrc.c revision 994689c1
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 1096 if (((fd = creat(name, 0666)) == -1) 1097 || (write(fd, string, strlen(string)) == -1)) 1098 return (False); 1099 1100 if (close(fd) == -1) 1101 return (False); 1102 1103 return (True); 1104} 1105 1106 1107/* 1108 * Function: 1109 * StorePiecesInString 1110 * 1111 * Parameters: 1112 * src - the multiSrc object to gather data from 1113 * 1114 * Description: 1115 * Store the pieces in memory into a char string. 1116 * 1117 * Returns: 1118 * mb_string: Caller must free 1119 * (or) 1120 * NULL: conversion error 1121 */ 1122static String 1123StorePiecesInString(MultiSrcObject src) 1124{ 1125 wchar_t *wc_string; 1126 char *mb_string; 1127 int char_count = src->multi_src.length; 1128 XawTextPosition first; 1129 MultiPiece *piece; 1130 1131 /* I believe the char_count + 1 and the NULL termination are unneeded! FS */ 1132 wc_string = (wchar_t*)XtMalloc((char_count + 1) * sizeof(wchar_t)); 1133 1134 for (first = 0, piece = src->multi_src.first_piece ; piece != NULL; 1135 first += piece->used, piece = piece->next) 1136 (void)wcsncpy(wc_string + first, piece->text, piece->used); 1137 1138 wc_string[char_count] = 0; 1139 1140 /* This will refill all pieces to capacity */ 1141 if (src->multi_src.data_compression) { 1142 FreeAllPieces(src); 1143 LoadPieces(src, NULL, (char *)wc_string); 1144 } 1145 1146 /* Lastly, convert it to a MB format and send it back */ 1147 mb_string = _XawTextWCToMB(XtDisplayOfObject((Widget)src), 1148 wc_string, &char_count); 1149 1150 /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED */ 1151 XtFree((char*)wc_string); 1152 1153 return (mb_string); 1154} 1155 1156/* 1157 * Function: 1158 * InitStringOrFile 1159 * 1160 * Parameters: 1161 * src - MultiSource 1162 * 1163 * Description: 1164 * Initializes the string or file. 1165 */ 1166static FILE * 1167InitStringOrFile(MultiSrcObject src, Bool newString) 1168{ 1169 mode_t open_mode = 0; 1170 const char *fdopen_mode = NULL; 1171 int fd; 1172 FILE *file; 1173 Display *d = XtDisplayOfObject((Widget)src); 1174 1175 if (src->multi_src.type == XawAsciiString) { 1176 if (src->multi_src.string == NULL) 1177 src->multi_src.length = 0; 1178 1179 else if (!src->multi_src.use_string_in_place) { 1180 int length; 1181 String temp = XtNewString((char *)src->multi_src.string); 1182 1183 if (src->multi_src.allocated_string) 1184 XtFree((char *)src->multi_src.string); 1185 src->multi_src.allocated_string = True; 1186 src->multi_src.string = temp; 1187 1188 length = strlen((char *)src->multi_src.string); 1189 1190 /* Wasteful, throwing away the WC string, but need side effect! */ 1191 (void)_XawTextMBToWC(d, (char *)src->multi_src.string, &length); 1192 src->multi_src.length = (XawTextPosition)length; 1193 } 1194 else { 1195 src->multi_src.length = strlen((char *)src->multi_src.string); 1196 /* In case the length resource is incorrectly set */ 1197 if (src->multi_src.length > src->multi_src.multi_length) 1198 src->multi_src.multi_length = src->multi_src.length; 1199 1200 if (src->multi_src.multi_length == MAGIC_VALUE) 1201 src->multi_src.piece_size = src->multi_src.length; 1202 else 1203 src->multi_src.piece_size = src->multi_src.multi_length + 1; 1204 } 1205 1206 return (NULL); 1207 } 1208 1209 /* 1210 * type is XawAsciiFile 1211 */ 1212 src->multi_src.is_tempfile = False; 1213 1214 switch (src->text_src.edit_mode) { 1215 case XawtextRead: 1216 if (src->multi_src.string == NULL) 1217 XtErrorMsg("NoFile", "multiSourceCreate", "XawError", 1218 "Creating a read only disk widget and no file specified.", 1219 NULL, 0); 1220 open_mode = O_RDONLY; 1221 fdopen_mode = "r"; 1222 break; 1223 case XawtextAppend: 1224 case XawtextEdit: 1225 if (src->multi_src.string == NULL) { 1226 src->multi_src.string = "*multi-src*"; 1227 src->multi_src.is_tempfile = True; 1228 } 1229 else { 1230/* O_NOFOLLOW is a BSD & Linux extension */ 1231#ifdef O_NOFOLLOW 1232 open_mode = O_RDWR | O_NOFOLLOW; 1233#else 1234 open_mode = O_RDWR; /* unsafe; subject to race conditions */ 1235#endif 1236 fdopen_mode = "r+"; 1237 } 1238 break; 1239 default: 1240 XtErrorMsg("badMode", "multiSourceCreate", "XawError", 1241 "Bad editMode for multi source; must be " 1242 "Read, Append or Edit.", NULL, NULL); 1243 } 1244 1245 /* If is_tempfile, allocate a private copy of the text 1246 * Unlikely to be changed, just to set allocated_string */ 1247 if (newString || src->multi_src.is_tempfile) { 1248 String temp = XtNewString((char *)src->multi_src.string); 1249 1250 if (src->multi_src.allocated_string) 1251 XtFree((char *)src->multi_src.string); 1252 src->multi_src.string = temp; 1253 src->multi_src.allocated_string = True; 1254 } 1255 1256 if (!src->multi_src.is_tempfile) { 1257 if ((fd = open((char *)src->multi_src.string, open_mode, 0666)) != -1) { 1258 if ((file = fdopen(fd, fdopen_mode)) != NULL) { 1259 (void)fseek(file, 0, SEEK_END); 1260 src->multi_src.length = (XawTextPosition)ftell(file); 1261 return(file); 1262 } 1263 } 1264 { 1265 String params[2]; 1266 Cardinal num_params = 2; 1267 1268 params[0] = (String)src->multi_src.string; 1269 params[1] = strerror(errno); 1270 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), 1271 "openError", "multiSourceCreate", "XawWarning", 1272 "Cannot open file %s; %s", params, &num_params); 1273 } 1274 } 1275 src->multi_src.length = 0; 1276 return (NULL); 1277} 1278 1279/* LoadPieces: This routine takes either the MB contents of open file 1280 `file' or the MB contents of string or the MB contents of 1281 src->multi_src.string and places them in Pieces in WC format. 1282 1283 CAUTION: You must have src->multi_src.length set to file length bytes 1284 when src->multi_src.type == XawAsciiFile. src->multi_src.length must be 1285 the length of the parameter string if string is non-NULL 1286*/ 1287static void 1288LoadPieces(MultiSrcObject src, FILE *file, char *string) 1289{ 1290 Display *d = XtDisplayOfObject((Widget)src); 1291 wchar_t* local_str, *ptr; 1292 MultiPiece* piece = NULL; 1293 XawTextPosition left; 1294 int bytes = sizeof(wchar_t); 1295 char* temp_mb_holder = NULL; 1296 1297 /* 1298 * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg 1299 * in as MB length, out as WC length. We want local_length to be 1300 * WC count. 1301 */ 1302 int local_length = src->multi_src.length; 1303 1304 if (string != NULL) { 1305 /* 1306 * ASSERT: IF our caller passed a non-null string, THEN 1307 * src->multi_src.length is currently string's * byte count, 1308 * AND string is in a MB format 1309 */ 1310 local_str = _XawTextMBToWC(d, (char *)string, &local_length); 1311 src->multi_src.length = (XawTextPosition) local_length; 1312 } 1313 else if (src->multi_src.type != XawAsciiFile) { 1314 /* 1315 * here, we are not changing the contents, just reloading, 1316 * so don't change len... 1317 */ 1318 local_length = src->multi_src.string ? 1319 strlen((char *)src->multi_src.string) : 0; 1320 local_str = _XawTextMBToWC(d, (char *)src->multi_src.string, 1321 &local_length); 1322 } 1323 else { 1324 if (src->multi_src.length != 0) { 1325 temp_mb_holder = 1326 XtMalloc((src->multi_src.length + 1) * sizeof(unsigned char)); 1327 fseek(file, 0, 0); 1328 src->multi_src.length = fread(temp_mb_holder, 1329 (Size_t)sizeof(unsigned char), 1330 (Size_t)src->multi_src.length, file); 1331 if (src->multi_src.length <= 0) 1332 XtAppErrorMsg(XtWidgetToApplicationContext ((Widget) src), 1333 "readError", "multiSource", "XawError", 1334 "fread returned error.", NULL, NULL); 1335 local_length = src->multi_src.length; 1336 local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length); 1337 src->multi_src.length = local_length; 1338 1339 if (local_str == 0) { 1340 String params[2]; 1341 Cardinal num_params; 1342 static char err_text[] = 1343 "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>"; 1344 1345 params[0] = XtName(XtParent((Widget)src)); 1346 params[1] = src->multi_src.string; 1347 num_params = 2; 1348 1349 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), 1350 "readLocaleError", "multiSource", "XawError", 1351 "%s: The file `%s' contains characters " 1352 "not representable in this locale.", 1353 params, &num_params); 1354 src->multi_src.length = sizeof err_text; 1355 local_length = src->multi_src.length; 1356 local_str = _XawTextMBToWC(d, err_text, &local_length); 1357 src->multi_src.length = local_length; 1358 } 1359 } 1360 else 1361 /* ASSERT that since following while loop looks at local_length 1362 this isn't needed. Sheeran, Omron KK, 1993/07/15 1363 temp_mb_holder[src->multi_src.length] = '\0'; */ 1364 local_str = (wchar_t*)temp_mb_holder; 1365 } 1366 1367 if (src->multi_src.use_string_in_place) { 1368 piece = AllocNewPiece(src, piece); 1369 piece->used = Min(src->multi_src.length, src->multi_src.piece_size); 1370 piece->text = (wchar_t*)src->multi_src.string; 1371 return; 1372 } 1373 1374 ptr = local_str; 1375 left = local_length; 1376 1377 do { 1378 piece = AllocNewPiece(src, piece); 1379 1380 piece->text = (wchar_t*)XtMalloc((unsigned)(src->multi_src.piece_size 1381 * bytes)); 1382 piece->used = Min(left, src->multi_src.piece_size); 1383 if (piece->used != 0) 1384 (void)wcsncpy(piece->text, ptr, piece->used); 1385 1386 left -= piece->used; 1387 ptr += piece->used; 1388 } while (left > 0); 1389 1390 if (temp_mb_holder) 1391 XtFree((char*)temp_mb_holder); 1392} 1393 1394/* 1395 * Function: 1396 * AllocNewPiece 1397 * 1398 * Parameters: 1399 * src - MultiSrc Widget 1400 * prev - the piece just before this one, or NULL 1401 * 1402 * Description: 1403 * Allocates a new piece of memory. 1404 * 1405 * Returns: 1406 * The allocated piece 1407 */ 1408static MultiPiece * 1409AllocNewPiece(MultiSrcObject src, MultiPiece *prev) 1410{ 1411 MultiPiece *piece = XtNew(MultiPiece); 1412 1413 if (prev == NULL) { 1414 src->multi_src.first_piece = piece; 1415 piece->next = NULL; 1416 } 1417 else { 1418 if (prev->next != NULL) 1419 (prev->next)->prev = piece; 1420 piece->next = prev->next; 1421 prev->next = piece; 1422 } 1423 1424 piece->prev = prev; 1425 1426 return (piece); 1427} 1428 1429/* 1430 * Function: 1431 * FreeAllPieces 1432 * 1433 * Parameters: 1434 * src - MultiSrc Widget 1435 * 1436 * Description: 1437 * Frees all the pieces 1438 */ 1439static void 1440FreeAllPieces(MultiSrcObject src) 1441{ 1442 MultiPiece *next, *first = src->multi_src.first_piece; 1443 1444#ifdef DEBUG 1445 if (first->prev != NULL) 1446 printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n"); 1447#endif 1448 1449 for (; first != NULL ; first = next) { 1450 next = first->next; 1451 RemovePiece(src, first); 1452 } 1453} 1454 1455/* 1456 * Function: 1457 * RemovePiece 1458 * 1459 * Parameters: 1460 * piece - piece to remove 1461 * 1462 * Description: 1463 * Removes a piece from the list. 1464 */ 1465static void 1466RemovePiece(MultiSrcObject src, MultiPiece *piece) 1467{ 1468 if (piece->prev == NULL) 1469 src->multi_src.first_piece = piece->next; 1470 else 1471 piece->prev->next = piece->next; 1472 1473 if (piece->next != NULL) 1474 piece->next->prev = piece->prev; 1475 1476 if (!src->multi_src.use_string_in_place) 1477 XtFree((char *)piece->text); 1478 1479 XtFree((char *)piece); 1480} 1481 1482/* 1483 * Function: 1484 * FindPiece 1485 * 1486 * Parameters: 1487 * src - MultiSrc Widget 1488 * position - position that we are searching for 1489 * first - position of the first character in this piece (return) 1490 * 1491 * Description: 1492 * Finds the piece containing the position indicated. 1493 * 1494 * Returns: 1495 * Piece that contains this position 1496 */ 1497static MultiPiece * 1498FindPiece(MultiSrcObject src, XawTextPosition position, XawTextPosition *first) 1499{ 1500 MultiPiece *old_piece, *piece; 1501 XawTextPosition temp; 1502 1503 for (old_piece = NULL, piece = src->multi_src.first_piece, temp = 0; 1504 piece; old_piece = piece, piece = piece->next) 1505 if ((temp += piece->used) > position) { 1506 *first = temp - piece->used; 1507 return (piece); 1508 } 1509 1510 *first = temp - (old_piece ? old_piece->used : 0); 1511 1512 return (old_piece); /* if we run off the end the return the last piece */ 1513} 1514 1515/* 1516 * Function: 1517 * BreakPiece 1518 * 1519 * Parameters: 1520 * src - MultiSrc Widget 1521 * piece - piece to break 1522 * 1523 * Description: 1524 * Breaks a full piece into two new pieces. 1525 */ 1526#define HALF_PIECE (src->multi_src.piece_size >> 1) 1527static void 1528BreakPiece(MultiSrcObject src, MultiPiece *piece) 1529{ 1530 MultiPiece *cnew = AllocNewPiece(src, piece); 1531 1532 cnew->text = (wchar_t *) 1533 XtMalloc(src->multi_src.piece_size * sizeof(wchar_t)); 1534 (void)wcsncpy(cnew->text, piece->text + HALF_PIECE, 1535 src->multi_src.piece_size - HALF_PIECE); 1536 piece->used = HALF_PIECE; 1537 cnew->used = src->multi_src.piece_size - HALF_PIECE; 1538} 1539 1540/*ARGSUSED*/ 1541static void 1542CvtStringToMultiType(XrmValuePtr args, Cardinal *num_args, 1543 XrmValuePtr fromVal, XrmValuePtr toVal) 1544{ 1545 static XawAsciiType type = XawAsciiString; 1546 XrmQuark q; 1547 char name[7]; 1548 1549 XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); 1550 q = XrmStringToQuark(name); 1551 1552 if (q == Qstring) 1553 type = XawAsciiString; 1554 if (q == Qfile) 1555 type = XawAsciiFile; 1556 else { 1557 toVal->size = 0; 1558 toVal->addr = NULL; 1559 XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType); 1560 } 1561 1562 toVal->size = sizeof(XawAsciiType); 1563 toVal->addr = (XPointer)&type; 1564} 1565 1566/*ARGSUSED*/ 1567static Boolean 1568CvtMultiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, 1569 XrmValuePtr fromVal, XrmValuePtr toVal, 1570 XtPointer *data) 1571{ 1572 static String buffer; 1573 Cardinal size; 1574 1575 switch (*(XawAsciiType *)fromVal->addr) { 1576 case XawAsciiFile: 1577 buffer = XtEfile; 1578 break; 1579 case XawAsciiString: 1580 buffer = XtEstring; 1581 break; 1582 default: 1583 XawTypeToStringWarning(dpy, XtRAsciiType); 1584 toVal->addr = NULL; 1585 toVal->size = 0; 1586 return (False); 1587 } 1588 1589 size = strlen(buffer) + 1; 1590 if (toVal->addr != NULL) { 1591 if (toVal->size < size) { 1592 toVal->size = size; 1593 return (False); 1594 } 1595 strcpy((char *)toVal->addr, buffer); 1596 } 1597 else 1598 toVal->addr = (XPointer)buffer; 1599 toVal->size = sizeof(String); 1600 1601 return (True); 1602} 1603 1604/*ARGSUSED*/ 1605static void 1606GetDefaultPieceSize(Widget w, int offset, XrmValue *value) 1607{ 1608 static XPointer pagesize; 1609 1610 if (pagesize == 0) { 1611 pagesize = (XPointer)((long)_XawGetPageSize()); 1612 if (pagesize < (XPointer)BUFSIZ) 1613 pagesize = (XPointer)BUFSIZ; 1614 } 1615 1616 value->addr = (XPointer)&pagesize; 1617} 1618