MultiSrc.c revision 5b16253f
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 char * 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#ifndef OLDXAW 238 NULL 239#endif 240 }, 241 /* multi_src */ 242 { 243 NULL, /* extension */ 244 }, 245}; 246 247WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec; 248 249static XrmQuark Qstring, Qfile; 250 251/* 252 * Implementation 253 */ 254static void 255XawMultiSrcClassInitialize(void) 256{ 257 XawInitializeWidgetSet(); 258 Qstring = XrmPermStringToQuark(XtEstring); 259 Qfile = XrmPermStringToQuark(XtEfile); 260 XtAddConverter(XtRString, XtRMultiType, CvtStringToMultiType, NULL, 0); 261 XtSetTypeConverter(XtRMultiType, XtRString, CvtMultiTypeToString, NULL, 0, 262 XtCacheNone, NULL); 263} 264 265/* 266 * Function: 267 * XawMultiSrcInitialize 268 * 269 * Parameters: 270 * request - widget requested by the argument list 271 * cnew - the new widget with both resource and non resource values 272 * args - (unused) 273 * num_args - (unused) 274 * 275 * Description: 276 * Initializes the multi src object 277 */ 278/*ARGSUSED*/ 279static void 280XawMultiSrcInitialize(Widget request _X_UNUSED, Widget cnew, 281 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 282{ 283 MultiSrcObject src = (MultiSrcObject)cnew; 284 FILE *file; 285 286 /* 287 * Set correct flags (override resources) depending upon widget class 288 */ 289#ifdef OLDXAW 290 src->multi_src.changes = False; 291#else 292 src->text_src.changed = False; 293#endif 294 src->multi_src.allocated_string = False; 295 296 if (src->multi_src.use_string_in_place && src->multi_src.string == NULL) 297 src->multi_src.use_string_in_place = False; 298 299 file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile); 300 LoadPieces(src, file, NULL); 301 302 if (file != NULL) 303 fclose(file); 304 src->text_src.text_format = (XrmQuark)XawFmtWide; 305} 306 307/* 308 * Function: 309 * ReadText 310 * 311 * Parameters: 312 * w - MultiSource object 313 * pos - position of the text to retrieve 314 * text - text block that will contain returned text 315 * length - maximum number of characters to read 316 * 317 * Description: 318 * This function reads the source. 319 * 320 * Returns: 321 * The character position following the retrieved text. 322 */ 323static XawTextPosition 324ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length) 325{ 326 MultiSrcObject src = (MultiSrcObject)w; 327 XawTextPosition count, start; 328 MultiPiece *piece = FindPiece(src, pos, &start); 329 330 text->format = XawFmtWide; 331 text->firstPos = (int)pos; 332 text->ptr = (char *)(piece->text + (pos - start)); 333 count = piece->used - (pos - start); 334 text->length = (Max(0, (length > count) ? count : length)); 335 336 return (pos + text->length); 337} 338 339/* 340 * Function: 341 * ReplaceText 342 * 343 * Parameters: 344 * w - MultiSource object 345 * startPos - ends of text that will be removed 346 * endPos - "" 347 * text - new text to be inserted into buffer at startPos 348 * 349 * Description: 350 * Replaces a block of text with new text. 351 * 352 * Returns: 353 * XawEditDone on success, XawEditError otherwise 354 */ 355/*ARGSUSED*/ 356static int 357ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos, 358 XawTextBlock *u_text_p) 359{ 360 MultiSrcObject src = (MultiSrcObject)w; 361 MultiPiece *start_piece, *end_piece, *temp_piece; 362 XawTextPosition start_first, end_first; 363 int length, firstPos; 364 wchar_t *wptr; 365 Bool local_artificial_block = False; 366 XawTextBlock text; 367 368 /* STEP 1: The user handed me a text block called `u_text' that may be 369 * in either FMTWIDE or FMT8BIT (ie MB.) Later code needs the block 370 * `text' to hold FMTWIDE. So, this copies `u_text' to `text', and if 371 * `u_text' was MB, I knock it up to WIDE 372 */ 373 if (u_text_p->length == 0) /* if so, the block contents never ref'd */ 374 text.length = 0; 375 376 else if (u_text_p->format == XawFmtWide) { 377 local_artificial_block = False; /* don't have to free it ourselves */ 378 text.firstPos = u_text_p->firstPos; 379 text.length = u_text_p->length; 380 text.ptr = u_text_p->ptr; 381 } 382 else { 383 /* 384 * WARNING! u_text->firstPos and length are in units of CHAR, 385 * not CHARACTERS! 386 */ 387 local_artificial_block = True; /* have to free it ourselves */ 388 text.firstPos = 0; 389 text.length = u_text_p->length; /* _XawTextMBToWC converts this 390 * to wchar len 391 */ 392 393 text.ptr = (char*)_XawTextMBToWC(XtDisplay(XtParent(w)), 394 &u_text_p->ptr[u_text_p->firstPos], 395 &text.length); 396 397 /* I assert the following assignment is not needed - since Step 4 398 depends on length, it has no need of a terminating NULL. I think 399 the ASCII-version has the same needless NULL. */ 400 /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/ 401 } 402 403 /* STEP 2: some initialization... */ 404 if (src->text_src.edit_mode == XawtextRead) 405 return (XawEditError); 406 407 start_piece = FindPiece(src, startPos, &start_first); 408 end_piece = FindPiece(src, endPos, &end_first); 409 410 /* STEP 3: remove the empty pieces... */ 411 if (start_piece != end_piece) { 412 temp_piece = start_piece->next; 413 414 /* If empty and not the only piece then remove it */ 415 if (((start_piece->used = startPos - start_first) == 0) 416 && !(start_piece->next == NULL && start_piece->prev == NULL)) 417 RemovePiece(src, start_piece); 418 419 while (temp_piece != end_piece) { 420 temp_piece = temp_piece->next; 421 RemovePiece(src, temp_piece->prev); 422 } 423 end_piece->used -= endPos - end_first; 424 if (end_piece->used != 0) 425 memmove(end_piece->text, end_piece->text + endPos - end_first, 426 (size_t)end_piece->used * sizeof(wchar_t)); 427 } 428 else { /* We are fully in one piece */ 429 if ((start_piece->used -= endPos - startPos) == 0) { 430 if (!(start_piece->next == NULL && start_piece->prev == NULL)) 431 RemovePiece(src, start_piece); 432 } 433 else { 434 memmove(start_piece->text + (startPos - start_first), 435 start_piece->text + (endPos - start_first), 436 (size_t)(start_piece->used - (startPos - start_first)) * 437 sizeof(wchar_t)); 438 if (src->multi_src.use_string_in_place && 439 ((src->multi_src.length - (endPos - startPos)) 440 < src->multi_src.piece_size - 1)) 441 start_piece->text[src->multi_src.length - (endPos - startPos)] = 442 (wchar_t)0; 443 } 444 } 445 446 src->multi_src.length += text.length -(endPos - startPos); 447 448 /* STEP 4: insert the new stuff */ 449 if ( text.length != 0) { 450 start_piece = FindPiece(src, startPos, &start_first); 451 length = text.length; 452 firstPos = text.firstPos; 453 454 while (length > 0) { 455 wchar_t *ptr; 456 int fill; 457 458 if (src->multi_src.use_string_in_place) { 459 if (start_piece->used == src->multi_src.piece_size - 1) { 460 461 /* 462 * The string is used in place, then the string 463 * is not allowed to grow 464 */ 465 start_piece->used = src->multi_src.length = 466 src->multi_src.piece_size - 1; 467 468 start_piece->text[src->multi_src.length] = (wchar_t)0; 469 return (XawEditError); 470 } 471 } 472 473 if (start_piece->used == src->multi_src.piece_size) { 474 BreakPiece(src, start_piece); 475 start_piece = FindPiece(src, startPos, &start_first); 476 } 477 478 fill = Min((int)(src->multi_src.piece_size - start_piece->used), length); 479 480 ptr = start_piece->text + (startPos - start_first); 481 memmove(ptr + fill, ptr, (size_t)(start_piece->used - 482 (startPos - start_first)) * sizeof(wchar_t)); 483 wptr =(wchar_t *)text.ptr; 484 (void)wcsncpy(ptr, wptr + firstPos, (size_t)fill); 485 486 startPos += fill; 487 firstPos += fill; 488 start_piece->used += fill; 489 length -= fill; 490 } 491 } 492 493 if (local_artificial_block == True) 494 /* In other words, text is not the u_text that the user handed me but 495 one I made myself. I only care, because I need to free the string */ 496 XtFree(text.ptr); 497 498 if (src->multi_src.use_string_in_place) 499 start_piece->text[start_piece->used] = (wchar_t)0; 500 501#ifdef OLDXAW 502 src->multi_src.changes = True; 503 XtCallCallbacks(w, XtNcallback, NULL); 504#endif 505 506 return (XawEditDone); 507} 508 509/* 510 * Function: 511 * Scan 512 * 513 * Parameters: 514 * w - MultiSource widget 515 * position - position to start scanning 516 * type - type of thing to scan for 517 * dir - direction to scan 518 * count - which occurrence of this thing to search for 519 * include - whether or not to include the character found in 520 * the position that is returned 521 * 522 * Description: 523 * Scans the text source for the number and type of item specified. 524 * 525 * Returns: 526 * The position of the item found 527 * 528 * Note: 529 * While there are only 'n' characters in the file there are n+1 530 * possible cursor positions (one before the first character and 531 * one after the last character 532 */ 533static XawTextPosition 534Scan(Widget w, register XawTextPosition position, XawTextScanType type, 535 XawTextScanDirection dir, int count, Bool include) 536{ 537 MultiSrcObject src = (MultiSrcObject)w; 538 register char inc; 539 MultiPiece *piece; 540 XawTextPosition first, first_eol_position = position; 541 register wchar_t *ptr; 542 int cnt = count; 543 544 if (type == XawstAll) { 545 if (dir == XawsdRight) 546 return (src->multi_src.length); 547 return (0); 548 } 549 550 /* STEP 1: basic sanity checks */ 551 if (position > src->multi_src.length) 552 position = src->multi_src.length; 553 554 if (dir == XawsdRight) { 555 if (position == src->multi_src.length) 556 return (src->multi_src.length); 557 inc = 1; 558 } 559 else { 560 if (position == 0) 561 return (0); 562 inc = -1; 563 position--; 564 } 565 566 piece = FindPiece(src, position, &first); 567 568 if (piece->used == 0) 569 return (0); 570 571 ptr = (position - first) + piece->text; 572 573 switch (type) { 574 case XawstEOL: 575 case XawstParagraph: 576 case XawstWhiteSpace: 577 case XawstAlphaNumeric: 578 for (; cnt > 0 ; cnt--) { 579 Bool non_space = False, first_eol = True; 580 581 /*CONSTCOND*/ 582 while (True) { 583 register wchar_t c; 584 585 if (ptr < piece->text) { 586 piece = piece->prev; 587 if (piece == NULL) /* Beginning of text */ 588 return (0); 589 ptr = piece->text + piece->used - 1; 590 c = *ptr; 591 } 592 else if (ptr >= piece->text + piece->used) { 593 piece = piece->next; 594 if (piece == NULL) /* End of text */ 595 return (src->multi_src.length); 596 ptr = piece->text; 597 } 598 599 c = *ptr; 600 ptr += inc; 601 position += inc; 602 603 if (type == XawstAlphaNumeric) { 604 if (!iswalnum((wint_t)c)) { 605 if (non_space) 606 break; 607 } 608 else 609 non_space = True; 610 } 611 else if (type == XawstWhiteSpace) { 612 if (iswspace(c)) { 613 if (non_space) 614 break; 615 } 616 else 617 non_space = True; 618 } 619 else if (type == XawstEOL) { 620 if (c == _Xaw_atowc(XawLF)) 621 break; 622 } 623 else { /* XawstParagraph */ 624 if (first_eol) { 625 if (c == _Xaw_atowc(XawLF)) { 626 first_eol_position = position; 627 first_eol = False; 628 } 629 } 630 else 631 if (c == _Xaw_atowc(XawLF)) 632 break; 633 else if (!iswspace(c)) 634 first_eol = True; 635 } 636 } 637 } 638 if (!include) { 639 if (type == XawstParagraph) 640 position = first_eol_position; 641 if (count) 642 position -= inc; 643 } 644 break; 645 case XawstPositions: 646 position += count * inc; 647 break; 648 default: 649 break; 650 } 651 652 if (dir == XawsdLeft) 653 position++; 654 655 if (position >= src->multi_src.length) 656 return (src->multi_src.length); 657 if (position < 0) 658 return (0); 659 660 return (position); 661} 662 663/* 664 * Function: 665 * Search 666 * 667 * Parameters: 668 * w - MultiSource objecy 669 * position - position to start scanning 670 * dir - direction to scan 671 * text - text block to search for 672 * 673 * Description: 674 * Searches the text source for the text block passed. 675 * 676 * Returns: 677 * The position of the item found 678 */ 679static XawTextPosition 680Search(Widget w, register XawTextPosition position, XawTextScanDirection dir, 681 XawTextBlock *text) 682{ 683 MultiSrcObject src = (MultiSrcObject)w; 684 register int count = 0; 685 wchar_t *ptr; 686 wchar_t *wtarget; 687 int wtarget_len; 688 Display *d = XtDisplay(XtParent(w)); 689 MultiPiece *piece; 690 wchar_t *buf; 691 XawTextPosition first; 692 register char inc; 693 int cnt; 694 695 /* STEP 1: First, a brief sanity check */ 696 if (dir == XawsdRight) 697 inc = 1; 698 else { 699 inc = -1; 700 if (position == 0) 701 return (XawTextSearchError); 702 position--; 703 } 704 705 /* STEP 2: Ensure I have a local wide string.. */ 706 707 /* Since this widget stores 32bit chars, I check here to see if 708 I'm being passed a string claiming to be 8bit chars (ie, MB text.) 709 If that is the case, naturally I convert to 32bit format */ 710 711 /*if the block was FMT8BIT, length will convert to REAL wchar count below */ 712 wtarget_len = text->length; 713 714 if (text->format == XawFmtWide) 715 wtarget = &(((wchar_t*)text->ptr) [text->firstPos]); 716 else { 717 /* The following converts wtarget_len from byte len to wchar count */ 718 wtarget = _XawTextMBToWC(d, &text->ptr[text->firstPos], &wtarget_len); 719 } 720 721 /* OK, I can now assert that wtarget holds wide characters, wtarget_len 722 holds an accurate count of those characters, and that firstPos has been 723 effectively factored out of the following computations */ 724 725 /* STEP 3: SEARCH! */ 726 buf = (wchar_t *)XtMalloc((Cardinal)(sizeof(wchar_t) * (size_t)wtarget_len)); 727 (void)wcsncpy(buf, wtarget, (size_t)wtarget_len); 728 piece = FindPiece(src, position, &first); 729 ptr = (position - first) + piece->text; 730 731 /*CONSTCOND*/ 732 while (True) { 733 if (*ptr == (dir == XawsdRight ? *(buf + count) 734 : *(buf + wtarget_len - count - 1))) { 735 if (count == text->length - 1) 736 break; 737 else 738 count++; 739 } 740 else { 741 if (count != 0) { 742 position -=inc * count; 743 ptr -= inc * count; 744 } 745 count = 0; 746 } 747 748 ptr += inc; 749 position += inc; 750 751 while (ptr < piece->text) { 752 cnt = (int)(piece->text - ptr); 753 754 piece = piece->prev; 755 if (piece == NULL) { /* Beginning of text */ 756 XtFree((char *)buf); 757 return (XawTextSearchError); 758 } 759 ptr = piece->text + piece->used - cnt; 760 } 761 762 while (ptr >= piece->text + piece->used) { 763 cnt = (int)(ptr - (piece->text + piece->used)); 764 765 piece = piece->next; 766 if (piece == NULL) { /* End of text */ 767 XtFree((char *)buf); 768 return (XawTextSearchError); 769 } 770 ptr = piece->text + cnt; 771 } 772 } 773 774 XtFree((char *)buf); 775 if (dir == XawsdLeft) 776 return(position); 777 778 return(position - (wtarget_len - 1)); 779} 780 781/* 782 * Function: 783 * XawMultiSrcSetValues 784 * 785 * Parameters: 786 * current - current state of the widget 787 * request - what was requested 788 * cnew - what the widget will become 789 * args - representation of resources that have changed 790 * num_args - number of changed resources 791 * 792 * Description: 793 * Sets the values for the MultiSource. 794 * 795 * Returns: 796 * True if redisplay is needed 797 */ 798static Boolean 799XawMultiSrcSetValues(Widget current, Widget request _X_UNUSED, Widget cnew, 800 ArgList args, Cardinal *num_args) 801{ 802 MultiSrcObject src = (MultiSrcObject)cnew; 803 MultiSrcObject old_src = (MultiSrcObject)current; 804 XtAppContext app_con = XtWidgetToApplicationContext(cnew); 805 Bool total_reset = False, string_set = False; 806 FILE *file; 807 unsigned int i; 808 809 if (old_src->multi_src.use_string_in_place 810 != src->multi_src.use_string_in_place) { 811 XtAppWarning(app_con, 812 "MultiSrc: The XtNuseStringInPlace resources " 813 "may not be changed."); 814 src->multi_src.use_string_in_place = 815 old_src->multi_src.use_string_in_place; 816 } 817 818 for (i = 0; i < *num_args ; i++) 819 if (streq(args[i].name, XtNstring)) { 820 string_set = True; 821 break; 822 } 823 824 if (string_set || old_src->multi_src.type != src->multi_src.type) { 825 RemoveOldStringOrFile(old_src, string_set); 826 src->multi_src.allocated_string = old_src->multi_src.allocated_string; 827 file = InitStringOrFile(src, string_set); 828 829 LoadPieces(src, file, NULL); 830 if (file != NULL) 831 fclose(file); 832#ifndef OLDXAW 833 for (i = 0; i < src->text_src.num_text; i++) 834 /* Tell text widget what happened */ 835 XawTextSetSource(src->text_src.text[i], cnew, 0); 836#else 837 XawTextSetSource(XtParent(cnew), cnew, 0); 838#endif 839 total_reset = True; 840 } 841 842 if (old_src->multi_src.multi_length != src->multi_src.multi_length) 843 src->multi_src.piece_size = src->multi_src.multi_length + 1; 844 845 if ( !total_reset && old_src->multi_src.piece_size 846 != src->multi_src.piece_size) { 847 char * mb_string = StorePiecesInString(old_src); 848 849 if (mb_string != 0) { 850 FreeAllPieces(old_src); 851 LoadPieces(src, NULL, mb_string); 852 XtFree(mb_string); 853 } 854 else { 855 /* If the buffer holds bad chars, don't touch it... */ 856 XtAppWarningMsg(app_con, 857 "convertError", "multiSource", "XawError", 858 XtName(XtParent((Widget)old_src)), NULL, NULL); 859 XtAppWarningMsg(app_con, 860 "convertError", "multiSource", "XawError", 861 "Non-character code(s) in buffer.", NULL, NULL); 862 } 863 } 864 865 return (False); 866} 867 868static void 869XawMultiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args) 870{ 871 MultiSrcObject src = (MultiSrcObject)w; 872 unsigned int i; 873 874 if (src->multi_src.type == XawAsciiString) { 875 for (i = 0; i < *num_args ; i++) { 876 if (streq(args[i].name, XtNstring)) { 877 if (src->multi_src.use_string_in_place) 878 *((char **)args[i].value) = (char *) 879 src->multi_src.first_piece->text; 880 else if (_XawMultiSave(w)) /* If save successful */ 881 *((char **)args[i].value) = (char *)src->multi_src.string; 882 break; 883 } 884 } 885 } 886} 887 888static void 889XawMultiSrcDestroy(Widget w) 890{ 891 RemoveOldStringOrFile((MultiSrcObject) w, True); 892} 893 894/* 895 * Public routines 896 */ 897/* 898 * Function: 899 * XawMultiSourceFreeString 900 * 901 * Parameters: 902 * w - MultiSrc widget 903 * 904 * Description: 905 * Frees the string returned by a get values call 906 * on the string when the source is of type string. 907 * 908 * Note: 909 * The public interface is XawAsciiSourceFreeString! 910 */ 911void 912_XawMultiSourceFreeString(Widget w) 913{ 914 MultiSrcObject src = (MultiSrcObject)w; 915 916 if (src->multi_src.allocated_string) { 917 XtFree((char *)src->multi_src.string); 918 src->multi_src.allocated_string = False; 919 src->multi_src.string = NULL; 920 } 921} 922 923/* 924 * Function: 925 * _XawMultiSave 926 * 927 * Parameters: 928 * w - multiSrc Widget 929 * 930 * Description: 931 * Saves all the pieces into a file or string as required. 932 * 933 * Returns: 934 * True if the save was successful 935 * 936 * Note: 937 * The public interface is XawAsciiSave(w)! 938 */ 939Bool 940_XawMultiSave(Widget w) 941{ 942 MultiSrcObject src = (MultiSrcObject)w; 943 XtAppContext app_con = XtWidgetToApplicationContext(w); 944 char *mb_string; 945 946 /* 947 * If using the string in place then there is no need to play games 948 * to get the internal info into a readable string 949 */ 950 if (src->multi_src.use_string_in_place) 951 return (True); 952 953 if (src->multi_src.type == XawAsciiFile) { 954#ifdef OLDXAW 955 if (!src->multi_src.changes) 956#else 957 if (!src->text_src.changed) /* No changes to save */ 958#endif 959 return (True); 960 961 mb_string = StorePiecesInString(src); 962 963 if (mb_string != 0) { 964 if (WriteToFile(mb_string, (String)src->multi_src.string) == False) { 965 XtFree(mb_string); 966 return (False); 967 } 968 XtFree(mb_string); 969#ifndef OLDXAW 970 src->text_src.changed = False; 971#else 972 src->multi_src.changes = False; 973#endif 974 return (True); 975 } 976 else { 977 /* If the buffer holds bad chars, don't touch it... */ 978 XtAppWarningMsg(app_con, 979 "convertError", "multiSource", "XawError", 980 "Due to illegal characters, file not saved.", 981 NULL, NULL); 982 return (False); 983 } 984 } 985 else { 986 /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED? The manual 987 says this routine's only function is to save files to 988 disk. -Sheeran */ 989 mb_string = StorePiecesInString(src); 990 991 if (mb_string == 0) { 992 /* If the buffer holds bad chars, don't touch it... */ 993 XtAppWarningMsg(app_con, 994 "convertError", "multiSource", "XawError", 995 XtName(XtParent((Widget)src)), NULL, NULL); 996 return (False); 997 } 998 999 /* assert: mb_string holds good characters so the buffer is fine */ 1000 if (src->multi_src.allocated_string == True) 1001 XtFree((char *)src->multi_src.string); 1002 else 1003 src->multi_src.allocated_string = True; 1004 1005 src->multi_src.string = mb_string; 1006 } 1007#ifdef OLDXAW 1008 src->multi_src.changes = False; 1009#else 1010 src->text_src.changed = False; 1011#endif 1012 1013 return (True); 1014} 1015 1016/* 1017 * Function: 1018 * XawMultiSaveAsFile 1019 * 1020 * Parameters: 1021 * w - MultiSrc widget 1022 * name - name of the file to save this file into 1023 * 1024 * Description: 1025 * Save the current buffer as a file. 1026 * 1027 * Returns: 1028 * True if the save was successful 1029 * 1030 * Note: 1031 * The public interface is XawAsciiSaveAsFile! 1032 */ 1033Bool 1034_XawMultiSaveAsFile(Widget w, _Xconst char* name) 1035{ 1036 MultiSrcObject src = (MultiSrcObject)w; 1037 char * mb_string; 1038 Bool ret; 1039 1040 mb_string = StorePiecesInString(src); 1041 1042 if (mb_string != 0) { 1043 ret = WriteToFile(mb_string, (String)name); 1044 XtFree(mb_string); 1045 1046 return (ret); 1047 } 1048 1049 /* otherwise there was a conversion error. So print widget name too */ 1050 XtAppWarningMsg(XtWidgetToApplicationContext(w), 1051 "convertError", "multiSource", "XawError", 1052 XtName(XtParent(w)), NULL, NULL); 1053 1054 return (False); 1055} 1056 1057/* 1058 * Private Functions 1059 */ 1060static void 1061RemoveOldStringOrFile(MultiSrcObject src, Bool checkString) 1062{ 1063 FreeAllPieces(src); 1064 1065 if (checkString && src->multi_src.allocated_string) { 1066 XtFree((char *)src->multi_src.string); 1067 src->multi_src.allocated_string = False; 1068 src->multi_src.string = NULL; 1069 } 1070} 1071 1072/* 1073 * Function: 1074 * WriteToFile 1075 * 1076 * Parameters: 1077 * string - string to write 1078 * name - name of the file 1079 * 1080 * Description: 1081 * Write the string specified to the beginning of the file specified. 1082 * 1083 * Returns: 1084 * Returns True if successful, False otherwise 1085 */ 1086static Bool 1087WriteToFile(String string, String name) 1088{ 1089 int fd; 1090 Bool result = True; 1091 1092 if ((fd = creat(name, 0666)) == -1) 1093 return (False); 1094 1095 if (write(fd, string, strlen(string)) == -1) 1096 result = False; 1097 1098 if (close(fd) == -1) 1099 return (False); 1100 1101 return (result); 1102} 1103 1104 1105/* 1106 * Function: 1107 * StorePiecesInString 1108 * 1109 * Parameters: 1110 * src - the multiSrc object to gather data from 1111 * 1112 * Description: 1113 * Store the pieces in memory into a char string. 1114 * 1115 * Returns: 1116 * mb_string: Caller must free 1117 * (or) 1118 * NULL: conversion error 1119 */ 1120static char * 1121StorePiecesInString(MultiSrcObject src) 1122{ 1123 wchar_t *wc_string; 1124 char *mb_string; 1125 int char_count = (int)src->multi_src.length; 1126 XawTextPosition first; 1127 MultiPiece *piece; 1128 1129 /* I believe the char_count + 1 and the NULL termination are unneeded! FS */ 1130 wc_string = (wchar_t*)XtMalloc((Cardinal)((size_t)(char_count + 1) * sizeof(wchar_t))); 1131 1132 for (first = 0, piece = src->multi_src.first_piece ; piece != NULL; 1133 first += piece->used, piece = piece->next) 1134 (void)wcsncpy(wc_string + first, piece->text, (size_t)piece->used); 1135 1136 wc_string[char_count] = 0; 1137 1138 /* This will refill all pieces to capacity */ 1139 if (src->multi_src.data_compression) { 1140 FreeAllPieces(src); 1141 LoadPieces(src, NULL, (char *)wc_string); 1142 } 1143 1144 /* Lastly, convert it to a MB format and send it back */ 1145 mb_string = _XawTextWCToMB(XtDisplayOfObject((Widget)src), 1146 wc_string, &char_count); 1147 1148 /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED */ 1149 XtFree((char*)wc_string); 1150 1151 return (mb_string); 1152} 1153 1154/* 1155 * Function: 1156 * InitStringOrFile 1157 * 1158 * Parameters: 1159 * src - MultiSource 1160 * 1161 * Description: 1162 * Initializes the string or file. 1163 */ 1164static FILE * 1165InitStringOrFile(MultiSrcObject src, Bool newString) 1166{ 1167 mode_t open_mode = 0; 1168 const char *fdopen_mode = NULL; 1169 int fd; 1170 FILE *file; 1171 Display *d = XtDisplayOfObject((Widget)src); 1172 1173 if (src->multi_src.type == XawAsciiString) { 1174 if (src->multi_src.string == NULL) 1175 src->multi_src.length = 0; 1176 1177 else if (!src->multi_src.use_string_in_place) { 1178 int length; 1179 char * temp = XtNewString((char *)src->multi_src.string); 1180 1181 if (src->multi_src.allocated_string) 1182 XtFree((char *)src->multi_src.string); 1183 src->multi_src.allocated_string = True; 1184 src->multi_src.string = temp; 1185 1186 length = (int)strlen((char *)src->multi_src.string); 1187 1188 /* Wasteful, throwing away the WC string, but need side effect! */ 1189 (void)_XawTextMBToWC(d, (char *)src->multi_src.string, &length); 1190 src->multi_src.length = (XawTextPosition)length; 1191 } 1192 else { 1193 src->multi_src.length = (XawTextPosition)strlen((char *)src->multi_src.string); 1194 /* In case the length resource is incorrectly set */ 1195 if (src->multi_src.length > src->multi_src.multi_length) 1196 src->multi_src.multi_length = (int)src->multi_src.length; 1197 1198 if (src->multi_src.multi_length == MAGIC_VALUE) 1199 src->multi_src.piece_size = src->multi_src.length; 1200 else 1201 src->multi_src.piece_size = src->multi_src.multi_length + 1; 1202 } 1203 1204 return (NULL); 1205 } 1206 1207 /* 1208 * type is XawAsciiFile 1209 */ 1210 src->multi_src.is_tempfile = False; 1211 1212 switch (src->text_src.edit_mode) { 1213 case XawtextRead: 1214 if (src->multi_src.string == NULL) 1215 XtErrorMsg("NoFile", "multiSourceCreate", "XawError", 1216 "Creating a read only disk widget and no file specified.", 1217 NULL, 0); 1218 open_mode = O_RDONLY; 1219 fdopen_mode = "r"; 1220 break; 1221 case XawtextAppend: 1222 case XawtextEdit: 1223 if (src->multi_src.string == NULL) { 1224 src->multi_src.string = (char *)"*multi-src*"; 1225 src->multi_src.is_tempfile = True; 1226 } 1227 else { 1228/* O_NOFOLLOW is a BSD & Linux extension */ 1229#ifdef O_NOFOLLOW 1230 open_mode = O_RDWR | O_NOFOLLOW; 1231#else 1232 open_mode = O_RDWR; /* unsafe; subject to race conditions */ 1233#endif 1234 fdopen_mode = "r+"; 1235 } 1236 break; 1237 default: 1238 XtErrorMsg("badMode", "multiSourceCreate", "XawError", 1239 "Bad editMode for multi source; must be " 1240 "Read, Append or Edit.", NULL, NULL); 1241 } 1242 1243 /* If is_tempfile, allocate a private copy of the text 1244 * Unlikely to be changed, just to set allocated_string */ 1245 if (newString || src->multi_src.is_tempfile) { 1246 char * temp = XtNewString((char *)src->multi_src.string); 1247 1248 if (src->multi_src.allocated_string) 1249 XtFree((char *)src->multi_src.string); 1250 src->multi_src.string = temp; 1251 src->multi_src.allocated_string = True; 1252 } 1253 1254 if (!src->multi_src.is_tempfile) { 1255 if ((fd = open((char *)src->multi_src.string, (int)open_mode, 0666)) != -1) { 1256 if ((file = fdopen(fd, fdopen_mode)) != NULL) { 1257 (void)fseek(file, 0, SEEK_END); 1258 src->multi_src.length = (XawTextPosition)ftell(file); 1259 return(file); 1260 } 1261 else 1262 close(fd); 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 = (int)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 = (int)(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(((size_t)(src->multi_src.length + 1) * sizeof(unsigned char))); 1327 fseek(file, 0, SEEK_SET); 1328 src->multi_src.length = (XawTextPosition)fread(temp_mb_holder, 1329 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 = (int)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 = (int)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, (size_t)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((Cardinal)((size_t)src->multi_src.piece_size * sizeof(wchar_t))); 1534 (void)wcsncpy(cnew->text, piece->text + HALF_PIECE, 1535 (size_t)(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 _X_UNUSED, Cardinal *num_args _X_UNUSED, 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 _X_UNUSED, Cardinal *num_args _X_UNUSED, 1569 XrmValuePtr fromVal, XrmValuePtr toVal, 1570 XtPointer *data _X_UNUSED) 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 = (Cardinal)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 _X_UNUSED, int offset _X_UNUSED, 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