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