AsciiSrc.c revision 775e7de9
1/* $Xorg: AsciiSrc.c,v 1.4 2001/02/09 02:03:42 xorgcvs Exp $ */ 2 3/* 4 5Copyright 1989, 1994, 1998 The Open Group 6 7Permission to use, copy, modify, distribute, and sell this software and its 8documentation for any purpose is hereby granted without fee, provided that 9the above copyright notice appear in all copies and that both that 10copyright notice and this permission notice appear in supporting 11documentation. 12 13The above copyright notice and this permission notice shall be included in 14all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of The Open Group shall not be 24used in advertising or otherwise to promote the sale, use or other dealings 25in this Software without prior written authorization from The Open Group. 26 27*/ 28 29/* $XFree86: xc/lib/Xaw/AsciiSrc.c,v 1.33 2002/07/04 17:04:20 paulo Exp $ */ 30 31/* 32 * AsciiSrc.c - AsciiSrc object. (For use with the text widget). 33 * 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include <config.h> 38#endif 39#include <stdio.h> 40#include <stdlib.h> 41#include <ctype.h> 42#include <errno.h> 43#include <X11/IntrinsicP.h> 44#include <X11/StringDefs.h> 45#include <X11/Xos.h> 46#include <X11/Xfuncs.h> 47#include <X11/Xmu/CharSet.h> 48#include <X11/Xmu/Misc.h> 49#include <X11/Xaw/XawInit.h> 50#include <X11/Xaw/AsciiSrcP.h> 51#include <X11/Xaw/MultiSrcP.h> 52#ifndef OLDXAW 53#include <X11/Xaw/TextSinkP.h> 54#include <X11/Xaw/AsciiSinkP.h> 55#endif 56#include "Private.h" 57 58#include <sys/types.h> 59#include <sys/stat.h> 60#include <fcntl.h> 61 62#if (defined(ASCII_STRING) || defined(ASCII_DISK)) 63#include <X11/Xaw/AsciiText.h> /* for Widget Classes */ 64#endif 65 66#ifdef X_NOT_POSIX 67#define Off_t long 68#define Size_t unsigned int 69#else 70#define Off_t off_t 71#define Size_t size_t 72#endif 73 74#define MAGIC_VALUE ((XawTextPosition)-1) 75#define streq(a, b) (strcmp((a), (b)) == 0) 76 77/* 78 * Class Methods 79 */ 80static void XawAsciiSrcClassInitialize(void); 81static void XawAsciiSrcDestroy(Widget); 82static void XawAsciiSrcGetValuesHook(Widget, ArgList, Cardinal*); 83static void XawAsciiSrcInitialize(Widget, Widget, ArgList, Cardinal*); 84static Boolean XawAsciiSrcSetValues(Widget, Widget, Widget, 85 ArgList, Cardinal*); 86static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int); 87static int ReplaceText(Widget, XawTextPosition, XawTextPosition, 88 XawTextBlock*); 89static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, 90 XawTextScanDirection, int, Bool); 91static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, 92 XawTextBlock*); 93 94/* 95 * Prototypes 96 */ 97static Piece *AllocNewPiece(AsciiSrcObject, Piece*); 98static void BreakPiece(AsciiSrcObject, Piece*); 99static Boolean CvtAsciiTypeToString(Display*, XrmValuePtr, Cardinal*, 100 XrmValuePtr, XrmValuePtr, XtPointer*); 101static void CvtStringToAsciiType(XrmValuePtr, Cardinal*, 102 XrmValuePtr, XrmValuePtr); 103static Piece *FindPiece(AsciiSrcObject, XawTextPosition, XawTextPosition*); 104static void FreeAllPieces(AsciiSrcObject); 105static FILE *InitStringOrFile(AsciiSrcObject, Bool); 106static void LoadPieces(AsciiSrcObject, FILE*, char*); 107static void RemoveOldStringOrFile(AsciiSrcObject, Bool); 108static void RemovePiece(AsciiSrcObject, Piece*); 109static String StorePiecesInString(AsciiSrcObject); 110static Bool WriteToFile(String, String, unsigned); 111static Bool WritePiecesToFile(AsciiSrcObject, String); 112static void GetDefaultPieceSize(Widget, int, XrmValue*); 113 114/* 115 * More Prototypes 116 */ 117#ifdef ASCII_DISK 118Widget XawAsciiDiskSourceCreate(Widget, ArgList, Cardinal); 119#endif 120#ifdef ASCII_STRING 121Widget XawStringSourceCreate(Widget, ArgList, Cardinal); 122void XawTextSetLastPos(Widget, XawTextPosition); 123#endif 124 125/* 126 * Initialization 127 */ 128#define offset(field) XtOffsetOf(AsciiSrcRec, ascii_src.field) 129static XtResource resources[] = { 130 { 131 XtNstring, 132 XtCString, 133 XtRString, 134 sizeof(char*), 135 offset(string), 136 XtRString, 137 NULL 138 }, 139 { 140 XtNtype, 141 XtCType, 142 XtRAsciiType, 143 sizeof(XawAsciiType), 144 offset(type), 145 XtRImmediate, 146 (XtPointer)XawAsciiString 147 }, 148 { 149 XtNdataCompression, 150 XtCDataCompression, 151 XtRBoolean, 152 sizeof(Boolean), 153 offset(data_compression), 154 XtRImmediate, 155 (XtPointer)True 156 }, 157 { 158 XtNpieceSize, 159 XtCPieceSize, 160 XtRInt, 161 sizeof(XawTextPosition), 162 offset(piece_size), 163 XtRCallProc, 164 (XtPointer)GetDefaultPieceSize 165 }, 166#ifdef OLDXAW 167 { 168 XtNcallback, 169 XtCCallback, 170 XtRCallback, 171 sizeof(XtPointer), 172 offset(callback), 173 XtRCallback, 174 (XtPointer)NULL 175 }, 176#endif 177 { 178 XtNuseStringInPlace, 179 XtCUseStringInPlace, 180 XtRBoolean, 181 sizeof(Boolean), 182 offset(use_string_in_place), 183 XtRImmediate, 184 (XtPointer)False 185 }, 186 { 187 XtNlength, 188 XtCLength, 189 XtRInt, 190 sizeof(int), 191 offset(ascii_length), 192 XtRImmediate, 193 (XtPointer)MAGIC_VALUE 194 }, 195#ifdef ASCII_DISK 196 { 197 XtNfile, 198 XtCFile, 199 XtRString, 200 sizeof(String), 201 offset(filename), 202 XtRString, 203 NULL 204 }, 205#endif /* ASCII_DISK */ 206}; 207#undef offset 208 209 210#define Superclass (&textSrcClassRec) 211AsciiSrcClassRec asciiSrcClassRec = { 212 /* object */ 213 { 214 (WidgetClass)Superclass, /* superclass */ 215 "AsciiSrc", /* class_name */ 216 sizeof(AsciiSrcRec), /* widget_size */ 217 XawAsciiSrcClassInitialize, /* class_initialize */ 218 NULL, /* class_part_initialize */ 219 False, /* class_inited */ 220 XawAsciiSrcInitialize, /* initialize */ 221 NULL, /* initialize_hook */ 222 NULL, /* realize */ 223 NULL, /* actions */ 224 0, /* num_actions */ 225 resources, /* resources */ 226 XtNumber(resources), /* num_resources */ 227 NULLQUARK, /* xrm_class */ 228 False, /* compress_motion */ 229 False, /* compress_exposure */ 230 False, /* compress_enterleave */ 231 False, /* visible_interest */ 232 XawAsciiSrcDestroy, /* destroy */ 233 NULL, /* resize */ 234 NULL, /* expose */ 235 XawAsciiSrcSetValues, /* set_values */ 236 NULL, /* set_values_hook */ 237 NULL, /* set_values_almost */ 238 XawAsciiSrcGetValuesHook, /* get_values_hook */ 239 NULL, /* accept_focus */ 240 XtVersion, /* version */ 241 NULL, /* callback_private */ 242 NULL, /* tm_table */ 243 NULL, /* query_geometry */ 244 NULL, /* display_accelerator */ 245 NULL, /* extension */ 246 }, 247 /* text_src */ 248 { 249 ReadText, /* Read */ 250 ReplaceText, /* Replace */ 251 Scan, /* Scan */ 252 Search, /* Search */ 253 XtInheritSetSelection, /* SetSelection */ 254 XtInheritConvertSelection, /* ConvertSelection */ 255 }, 256 /* ascii_src */ 257 { 258 NULL, /* extension */ 259 }, 260}; 261 262WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec; 263 264static XrmQuark Qstring, Qfile; 265 266/* 267 * Implementation 268 */ 269/* 270 * Function: 271 * XawAsciiSrcClassInitialize() 272 * 273 * Description: 274 * Initializes the asciiSrcObjectClass and install the converters for 275 * AsciiType <-> String. 276 */ 277static void 278XawAsciiSrcClassInitialize(void) 279{ 280 XawInitializeWidgetSet(); 281 Qstring = XrmPermStringToQuark(XtEstring); 282 Qfile = XrmPermStringToQuark(XtEfile); 283 XtAddConverter(XtRString, XtRAsciiType, CvtStringToAsciiType, NULL, 0); 284 XtSetTypeConverter(XtRAsciiType, XtRString, CvtAsciiTypeToString, 285 NULL, 0, XtCacheNone, NULL); 286} 287 288/* 289 * Function: 290 * XawAsciiSrcInitialize 291 * 292 * Parameters: 293 * request - widget requested by the argument list 294 * cnew - new widget with both resource and non resource values 295 * args - (unused) 296 * num_args - (unused) 297 * 298 * Description: 299 * Initializes the ascii src object. 300 */ 301/*ARGSUSED*/ 302static void 303XawAsciiSrcInitialize(Widget request, Widget cnew, 304 ArgList args, Cardinal *num_args) 305{ 306 AsciiSrcObject src = (AsciiSrcObject)cnew; 307 FILE *file; 308 309 /* 310 * Set correct flags (override resources) depending upon widget class 311 */ 312 src->text_src.text_format = XawFmt8Bit; 313 314#ifdef ASCII_DISK 315 if (XtIsSubclass(XtParent(cnew), asciiDiskWidgetClass)) { 316 src->ascii_src.type = XawAsciiFile; 317 src->ascii_src.string = src->ascii_src.filename; 318 } 319#endif 320 321#ifdef ASCII_STRING 322 if (XtIsSubclass(XtParent(cnew), asciiStringWidgetClass)) { 323 src->ascii_src.use_string_in_place = True; 324 src->ascii_src.type = XawAsciiString; 325 } 326#endif 327 328#ifdef OLDXAW 329 src->ascii_src.changes = False; 330#else 331 src->text_src.changed = False; 332#endif 333 src->ascii_src.allocated_string = False; 334 335 if (src->ascii_src.use_string_in_place && src->ascii_src.string == NULL) 336 src->ascii_src.use_string_in_place = False; 337 338 file = InitStringOrFile(src, src->ascii_src.type == XawAsciiFile); 339 LoadPieces(src, file, NULL); 340 341 if (file != NULL) 342 fclose(file); 343} 344 345/* 346 * Function: 347 * ReadText 348 * 349 * Parameters: 350 * w - AsciiSource widget 351 * pos - position of the text to retreive. 352 * text - text block that will contain returned text 353 * length - maximum number of characters to read 354 * 355 * Description: 356 * This function reads the source. 357 * 358 * Returns: 359 * The character position following the retrieved text. 360 */ 361static XawTextPosition 362ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length) 363{ 364 AsciiSrcObject src = (AsciiSrcObject)w; 365 XawTextPosition count, start; 366 Piece *piece; 367#ifndef OLDXAW 368 XawTextAnchor *anchor; 369 XawTextEntity *entity; 370 XawTextPosition offset, end = pos + length; 371 Bool state; 372 373 end = XawMin(end, src->ascii_src.length); 374 while ((state = XawTextSourceAnchorAndEntity(w, pos, &anchor, &entity)) && 375 (entity->flags & XAW_TENTF_HIDE)) 376 pos = anchor->position + entity->offset + entity->length; 377 if (state == False || 378 !(entity->flags & XAW_TENTF_REPLACE)) { 379 while (entity) { 380 offset = anchor->position + entity->offset; 381 if (offset >= end) 382 break; 383 if (offset > pos && 384 (entity->flags & (XAW_TENTF_HIDE | XAW_TENTF_REPLACE))) { 385 end = XawMin(end, offset); 386 break; 387 } 388 if ((entity = entity->next) == NULL && 389 (anchor = XawTextSourceNextAnchor(w, anchor)) != NULL) 390 entity = anchor->entities; 391 } 392 } 393 else if (state && (entity->flags & XAW_TENTF_REPLACE) && pos < end) { 394 XawTextBlock *block = (XawTextBlock*)entity->data; 395 396 offset = anchor->position + entity->offset; 397 end = XawMin(end, offset + block->length); 398 if ((length = end - pos) < 0) 399 length = 0; 400 text->length = length; 401 text->format = XawFmt8Bit; 402 if (length == 0) { 403 text->firstPos = end = offset + entity->length; 404 text->ptr = ""; 405 } 406 else { 407 text->firstPos = pos; 408 text->ptr = block->ptr + (pos - offset); 409 if (pos + length < offset + block->length) 410 end = pos + length; /* there is data left to be read */ 411 else 412 end = offset + entity->length; 413 } 414 415 return (end); 416 } 417 418 if ((length = end - pos) < 0) 419 length = 0; 420#endif 421 422 piece = FindPiece(src, pos, &start); 423 text->firstPos = pos; 424 text->ptr = piece->text + (pos - start); 425 count = piece->used - (pos - start); 426 text->length = Max(0, (length > count) ? count : length); 427 text->format = XawFmt8Bit; 428 429 return (pos + text->length); 430} 431 432/* 433 * Function: 434 * ReplaceText 435 * 436 * Parameters: 437 * w - AsciiSource object 438 * startPos - ends of text that will be replaced 439 * endPos - "" 440 * text - new text to be inserted into buffer at startPos 441 * 442 * Description: 443 * Replaces a block of text with new text. 444 * 445 * Returns: 446 * XawEditDone on success, XawEditError otherwise 447 */ 448/*ARGSUSED*/ 449static int 450ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos, 451 XawTextBlock *text) 452{ 453 AsciiSrcObject src = (AsciiSrcObject)w; 454 Piece *start_piece, *end_piece, *temp_piece; 455 XawTextPosition start_first, end_first; 456 int length, firstPos; 457 458 /* 459 * Editing a read only source is not allowed 460 */ 461 if (src->text_src.edit_mode == XawtextRead) 462 return (XawEditError); 463 464 start_piece = FindPiece(src, startPos, &start_first); 465 end_piece = FindPiece(src, endPos, &end_first); 466 467#ifndef OLDXAW 468 /* 469 * This is a big hack, but I can't think about a clever way to know 470 * if the character being moved forward has a negative lbearing. 471 * 472 */ 473 if (start_piece->used) { 474 int i; 475 476 for (i = 0; i < src->text_src.num_text; i++) { 477 int line; 478 TextWidget ctx = (TextWidget)src->text_src.text[i]; 479 480 for (line = 0; line < ctx->text.lt.lines; line++) 481 if (startPos < ctx->text.lt.info[line + 1].position) 482 break; 483 if (i < ctx->text.lt.lines && 484 startPos > ctx->text.lt.info[i].position) { 485 AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink; 486 XawTextAnchor *anchor; 487 XawTextEntity *entity; 488 XawTextProperty *property; 489 XFontStruct *font; 490 491 if (XawTextSourceAnchorAndEntity(w, startPos, &anchor, &entity) && 492 (property = XawTextSinkGetProperty(ctx->text.sink, 493 entity->property)) != NULL && 494 (property->mask & XAW_TPROP_FONT)) 495 font = property->font; 496 else 497 font = sink->ascii_sink.font; 498 499 if (font->min_bounds.lbearing < 0) { 500 int lbearing = font->min_bounds.lbearing; 501 unsigned char c = *(unsigned char*) 502 (start_piece->text + (startPos - start_first)); 503 504 if (c == '\t' || c == '\n') 505 c = ' '; 506 else if ((c & 0177) < XawSP || c == 0177) { 507 if (sink->ascii_sink.display_nonprinting) 508 c = c > 0177 ? '\\' : c + '^'; 509 else 510 c = ' '; 511 } 512 if (font->per_char && 513 (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)) 514 lbearing = font->per_char[c - font->min_char_or_byte2].lbearing; 515 if (lbearing < 0) 516 _XawTextNeedsUpdating(ctx, startPos - 1, startPos); 517 } 518 } 519 } 520 } 521 522 523#endif 524 525 /* 526 * Remove Old Stuff 527 */ 528 if (start_piece != end_piece) { 529 temp_piece = start_piece->next; 530 531 /* 532 * If empty and not the only piece then remove it. 533 */ 534 if (((start_piece->used = startPos - start_first) == 0) 535 && !(start_piece->next == NULL && start_piece->prev == NULL)) 536 RemovePiece(src, start_piece); 537 538 while (temp_piece != end_piece) { 539 temp_piece = temp_piece->next; 540 RemovePiece(src, temp_piece->prev); 541 } 542 543 end_piece->used -= endPos - end_first; 544 if (end_piece->used != 0) 545 memmove(end_piece->text, end_piece->text + endPos - end_first, 546 (unsigned)end_piece->used); 547 } 548 else { /* We are fully in one piece */ 549 if ((start_piece->used -= endPos - startPos) == 0) { 550 if (!(start_piece->next == NULL && start_piece->prev == NULL)) 551 RemovePiece(src, start_piece); 552 } 553 else { 554 memmove(start_piece->text + (startPos - start_first), 555 start_piece->text + (endPos - start_first), 556 (unsigned)(start_piece->used - (startPos - start_first))); 557 if (src->ascii_src.use_string_in_place 558 && src->ascii_src.length - (endPos - startPos) 559 < src->ascii_src.piece_size - 1) 560 start_piece->text[src->ascii_src.length - (endPos - startPos)] = 561 '\0'; 562 } 563 } 564 565 src->ascii_src.length += -(endPos - startPos) + text->length; 566 567 if ( text->length != 0) { 568 /* 569 * Put in the New Stuff 570 */ 571 start_piece = FindPiece(src, startPos, &start_first); 572 573 length = text->length; 574 firstPos = text->firstPos; 575 576 while (length > 0) { 577 char *ptr; 578 int fill; 579 580 if (src->ascii_src.use_string_in_place) { 581 if (start_piece->used == src->ascii_src.piece_size - 1) { 582 /* 583 * If we are in ascii string emulation mode. Then the 584 * string is not allowed to grow 585 */ 586 start_piece->used = src->ascii_src.length = 587 src->ascii_src.piece_size - 1; 588 start_piece->text[src->ascii_src.length] = '\0'; 589 return (XawEditError); 590 } 591 } 592 593 if (start_piece->used == src->ascii_src.piece_size) { 594 BreakPiece(src, start_piece); 595 start_piece = FindPiece(src, startPos, &start_first); 596 } 597 598 fill = Min((int)(src->ascii_src.piece_size - start_piece->used), 599 length); 600 601 ptr = start_piece->text + (startPos - start_first); 602 memmove(ptr + fill, ptr, 603 (unsigned)(start_piece->used - (startPos - start_first))); 604 memcpy(ptr, text->ptr + firstPos, (unsigned)fill); 605 606 startPos += fill; 607 firstPos += fill; 608 start_piece->used += fill; 609 length -= fill; 610 } 611 } 612 613 if (src->ascii_src.use_string_in_place) 614 start_piece->text[start_piece->used] = '\0'; 615 616#ifdef OLDXAW 617 src->ascii_src.changes = True; 618 XtCallCallbacks(w, XtNcallback, NULL); 619#endif 620 621 return (XawEditDone); 622} 623 624/* 625 * Function: 626 * Scan 627 * 628 * Parameters: 629 * w - AsciiSource object 630 * position - position to start scanning 631 * type - type of thing to scan for 632 * dir - direction to scan 633 * count - which occurance if this thing to search for. 634 * include - whether or not to include the character found in 635 * the position that is returned 636 * 637 * Description: 638 * Scans the text source for the number and type of item specified. 639 * 640 * Returns: 641 * The position of the item found 642 * 643 * Note: 644 * While there are only 'n' characters in the file there are n+1 645 * possible cursor positions (one before the first character and 646 * one after the last character 647 */ 648static XawTextPosition 649Scan(Widget w, register XawTextPosition position, XawTextScanType type, 650 XawTextScanDirection dir, int count, Bool include) 651{ 652 AsciiSrcObject src = (AsciiSrcObject)w; 653 Piece *piece; 654 XawTextPosition first, first_eol_position = 0; 655 register char *ptr, *lim; 656 register int cnt = count; 657 register unsigned char c; 658 659 if (dir == XawsdLeft) { 660 if (position <= 0) 661 return (0); 662 --position; 663 } 664 else if (position >= src->ascii_src.length) 665 return (src->ascii_src.length); 666 667 piece = FindPiece(src, position, &first); 668 if (piece->used == 0) 669 return (0); 670 671 ptr = (position - first) + piece->text; 672 673 if (dir == XawsdRight) { 674 lim = piece->text + piece->used; 675 switch (type) { 676 case XawstEOL: 677 case XawstParagraph: 678 case XawstWhiteSpace: 679 case XawstAlphaNumeric: 680 for (; cnt > 0; cnt--) { 681 Bool non_space = False, first_eol = True; 682 683 /*CONSTCOND*/ 684 while (True) { 685 if (ptr >= lim) { 686 piece = piece->next; 687 if (piece == NULL) /* End of text */ 688 return (src->ascii_src.length); 689 ptr = piece->text; 690 lim = piece->text + piece->used; 691 } 692 693 c = *ptr++; 694 ++position; 695 696 if (type == XawstEOL) { 697 if (c == '\n') 698 break; 699 } 700 else if (type == XawstAlphaNumeric) { 701 if (!isalnum(c)) { 702 if (non_space) 703 break; 704 } 705 else 706 non_space = True; 707 } 708 else if (type == XawstWhiteSpace) { 709 if (isspace(c)) { 710 if (non_space) 711 break; 712 } 713 else 714 non_space = True; 715 } 716 else { /* XawstParagraph */ 717 if (first_eol) { 718 if (c == '\n') { 719 first_eol_position = position; 720 first_eol = False; 721 } 722 } 723 else if (c == '\n') 724 break; 725 else if (!isspace(c)) 726 first_eol = True; 727 } 728 } 729 } 730 break; 731 case XawstPositions: 732 position += count; 733 return (position < src->ascii_src.length ? 734 position : src->ascii_src.length); 735 case XawstAll: 736 return (src->ascii_src.length); 737 default: 738 break; 739 } 740 if (!include) { 741 if (type == XawstParagraph) 742 position = first_eol_position; 743 if (count) 744 --position; 745 } 746 } 747 else { 748 lim = piece->text; 749 switch (type) { 750 case XawstEOL: 751 case XawstParagraph: 752 case XawstWhiteSpace: 753 case XawstAlphaNumeric: 754 for (; cnt > 0; cnt--) { 755 Bool non_space = False, first_eol = True; 756 757 /*CONSTCOND*/ 758 while (True) { 759 if (ptr < lim) { 760 piece = piece->prev; 761 if (piece == NULL) /* Begining of text */ 762 return (0); 763 ptr = piece->text + piece->used - 1; 764 lim = piece->text; 765 } 766 767 c = *ptr--; 768 --position; 769 770 if (type == XawstEOL) { 771 if (c == '\n') 772 break; 773 } 774 else if (type == XawstAlphaNumeric) { 775 if (!isalnum(c)) { 776 if (non_space) 777 break; 778 } 779 else 780 non_space = True; 781 } 782 else if (type == XawstWhiteSpace) { 783 if (isspace(c)) { 784 if (non_space) 785 break; 786 } 787 else 788 non_space = True; 789 } 790 else { /* XawstParagraph */ 791 if (first_eol) { 792 if (c == '\n') { 793 first_eol_position = position; 794 first_eol = False; 795 } 796 } 797 else if (c == '\n') 798 break; 799 else if (!isspace(c)) 800 first_eol = True; 801 } 802 } 803 } 804 break; 805 case XawstPositions: 806 position -= count - 1; 807 return (position > 0 ? position : 0); 808 case XawstAll: 809 return (0); 810 default: 811 break; 812 } 813 if (!include) { 814 if (type == XawstParagraph) 815 position = first_eol_position; 816 if (count) 817 ++position; 818 } 819 position++; 820 } 821 822 return (position); 823} 824 825/* 826 * Function: 827 * Search 828 * 829 * Parameters: 830 * w - AsciiSource object 831 * position - the position to start scanning 832 * dir - direction to scan 833 * text - text block to search for 834 * 835 * Description: 836 * Searchs the text source for the text block passed. 837 * 838 * Returns: 839 * The position of the item found 840 */ 841static XawTextPosition 842Search(Widget w, register XawTextPosition position, XawTextScanDirection dir, 843 XawTextBlock *text) 844{ 845 AsciiSrcObject src = (AsciiSrcObject)w; 846 register int count = 0; 847 register char *ptr, c; 848 char *str; 849 Piece *piece; 850 char *buf; 851 XawTextPosition first; 852 int cnt, case_sensitive; 853 854 if (dir == XawsdLeft) { 855 if (position == 0) 856 return (XawTextSearchError); 857 position--; 858 } 859 860 buf = XtMalloc((unsigned)sizeof(unsigned char) * text->length); 861 memcpy(buf, text->ptr, (unsigned)text->length); 862 piece = FindPiece(src, position, &first); 863 ptr = (position - first) + piece->text; 864 case_sensitive = text->firstPos; 865 866 if (dir == XawsdRight) { 867 str = buf; 868 c = *str; 869 /*CONSTCOND*/ 870 while (1) { 871 if (*ptr++ == c 872 || (case_sensitive && isalpha(c) && isalpha(ptr[-1]) 873 && toupper(c) == toupper(ptr[-1]))) { 874 if (++count == text->length) 875 break; 876 c = *++str; 877 } 878 else if (count) { 879 ptr -= count; 880 str -= count; 881 position -= count; 882 count = 0; 883 c = *str; 884 885 if (ptr < piece->text) { 886 do { 887 cnt = piece->text - ptr; 888 piece = piece->prev; 889 if (piece == NULL) { 890 XtFree(buf); 891 return (XawTextSearchError); 892 } 893 ptr = piece->text + piece->used - cnt; 894 } while (ptr < piece->text); 895 } 896 } 897 position++; 898 if (ptr >= (piece->text + piece->used)) { 899 do { 900 cnt = ptr - (piece->text + piece->used); 901 piece = piece->next; 902 if (piece == NULL) { 903 XtFree(buf); 904 return (XawTextSearchError); 905 } 906 ptr = piece->text + cnt; 907 } while (ptr >= (piece->text + piece->used)); 908 } 909 } 910 911 position -= text->length - 1; 912 } 913 else { 914 str = buf + text->length - 1; 915 c = *str; 916 /*CONSTCOND*/ 917 while (1) { 918 if (*ptr-- == c 919 || (case_sensitive && isalpha(c) && isalpha(ptr[1]) 920 && toupper(c) == toupper(ptr[1]))) { 921 if (++count == text->length) 922 break; 923 c = *--str; 924 } 925 else if (count) { 926 ptr += count; 927 str += count; 928 position += count; 929 count = 0; 930 c = *str; 931 932 if (ptr >= (piece->text + piece->used)) { 933 do { 934 cnt = ptr - (piece->text + piece->used); 935 piece = piece->next; 936 if (piece == NULL) { 937 XtFree(buf); 938 return (XawTextSearchError); 939 } 940 ptr = piece->text + cnt; 941 } while (ptr >= (piece->text + piece->used)); 942 } 943 } 944 position--; 945 if (ptr < piece->text) { 946 do { 947 cnt = piece->text - ptr; 948 piece = piece->prev; 949 if (piece == NULL) { 950 XtFree(buf); 951 return (XawTextSearchError); 952 } 953 ptr = piece->text + piece->used - cnt; 954 } while (ptr < piece->text); 955 } 956 } 957 } 958 959 XtFree(buf); 960 961 return (position); 962} 963 964/* 965 * Function: 966 * XawAsciiSrcSetValues 967 * 968 * Parameters: 969 * current - current state of the widget 970 * request - what was requested 971 * cnew - what the widget will become 972 * args - representation of changed resources 973 * num_args - number of resources that have changed 974 * 975 * Description: 976 * Sets the values for the AsciiSource. 977 * 978 * Returns: 979 * True if redisplay is needed 980 */ 981static Boolean 982XawAsciiSrcSetValues(Widget current, Widget request, Widget cnew, 983 ArgList args, Cardinal *num_args) 984{ 985 AsciiSrcObject src = (AsciiSrcObject)cnew; 986 AsciiSrcObject old_src = (AsciiSrcObject)current; 987 Bool total_reset = False, string_set = False; 988 FILE *file; 989 unsigned int i; 990 991 if (old_src->ascii_src.use_string_in_place 992 != src->ascii_src.use_string_in_place) { 993 XtAppWarning(XtWidgetToApplicationContext(cnew), 994 "AsciiSrc: The XtNuseStringInPlace resource may " 995 "not be changed."); 996 src->ascii_src.use_string_in_place = 997 old_src->ascii_src.use_string_in_place; 998 } 999 1000 for (i = 0; i < *num_args ; i++) 1001 if (streq(args[i].name, XtNstring)) { 1002 string_set = True; 1003 break; 1004 } 1005 1006 if (string_set || (old_src->ascii_src.type != src->ascii_src.type)) { 1007 RemoveOldStringOrFile(old_src, string_set); /* remove old info */ 1008 file = InitStringOrFile(src, string_set); /* Init new info */ 1009 LoadPieces(src, file, NULL); /* load new info into internal buffers */ 1010 if (file != NULL) 1011 fclose(file); 1012#ifndef OLDXAW 1013 for (i = 0; i < src->text_src.num_text; i++) 1014 /* Tell text widget what happened */ 1015 XawTextSetSource(src->text_src.text[i], cnew, 0); 1016#else 1017 XawTextSetSource(XtParent(cnew), cnew, 0); 1018#endif 1019 total_reset = True; 1020 } 1021 1022 if (old_src->ascii_src.ascii_length != src->ascii_src.ascii_length) 1023 src->ascii_src.piece_size = src->ascii_src.ascii_length + 1; 1024 1025 if (!total_reset && 1026 old_src->ascii_src.piece_size != src->ascii_src.piece_size) { 1027 String string = StorePiecesInString(old_src); 1028 1029 FreeAllPieces(old_src); 1030 LoadPieces(src, NULL, string); 1031 XtFree(string); 1032 } 1033 1034 return (False); 1035} 1036 1037/* 1038 * Function: 1039 * XawAsciiSrcGetValuesHook 1040 * 1041 * Parameters: 1042 * w - AsciiSource Widget 1043 * args - argument list 1044 * num_args - number of args 1045 * 1046 * Description: 1047 * This is a get values hook routine that sets the 1048 * values specific to the ascii source. 1049 */ 1050static void 1051XawAsciiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args) 1052{ 1053 AsciiSrcObject src = (AsciiSrcObject)w; 1054 unsigned int i; 1055 1056 if (src->ascii_src.type == XawAsciiString) { 1057 for (i = 0; i < *num_args ; i++) 1058 if (streq(args[i].name, XtNstring)) { 1059 if (src->ascii_src.use_string_in_place) 1060 *((char **)args[i].value) = src->ascii_src.first_piece->text; 1061 else if (XawAsciiSave(w)) /* If save sucessful */ 1062 *((char **)args[i].value) = src->ascii_src.string; 1063 break; 1064 } 1065 } 1066 } 1067 1068/* 1069 * Function: 1070 * XawAsciiSrcDestroy 1071 * 1072 * Parameters: 1073 * src - Ascii source object to free 1074 * 1075 * Description: 1076 * Destroys an ascii source (frees all data) 1077 */ 1078static void 1079XawAsciiSrcDestroy(Widget w) 1080{ 1081 RemoveOldStringOrFile((AsciiSrcObject) w, True); 1082} 1083 1084/* 1085 * Public routines 1086 */ 1087/* 1088 * Function: 1089 * XawAsciiSourceFreeString 1090 * 1091 * Parameters: 1092 * w - AsciiSrc widget 1093 * 1094 * Description: 1095 * Frees the string returned by a get values call 1096 * on the string when the source is of type string. 1097 */ 1098void 1099XawAsciiSourceFreeString(Widget w) 1100{ 1101 AsciiSrcObject src = (AsciiSrcObject)w; 1102 1103 /* If the src is really a multi, call the multi routine */ 1104 if (XtIsSubclass(w, multiSrcObjectClass)) { 1105 _XawMultiSourceFreeString(w); 1106 return; 1107 } 1108 else if (!XtIsSubclass(w, asciiSrcObjectClass)) { 1109 XtErrorMsg("bad argument", "asciiSource", "XawError", 1110 "XawAsciiSourceFreeString's parameter must be " 1111 "an asciiSrc or multiSrc.", 1112 NULL, NULL); 1113 } 1114 1115 if (src->ascii_src.allocated_string && src->ascii_src.type != XawAsciiFile) { 1116 src->ascii_src.allocated_string = False; 1117 XtFree(src->ascii_src.string); 1118 src->ascii_src.string = NULL; 1119 } 1120} 1121 1122/* 1123 * Function: 1124 * XawAsciiSave 1125 * 1126 * Parameters: 1127 * w - asciiSrc Widget 1128 * 1129 * Description: 1130 * Saves all the pieces into a file or string as required. 1131 * 1132 * Returns: 1133 * True if the save was successful 1134 */ 1135Bool 1136XawAsciiSave(Widget w) 1137{ 1138 AsciiSrcObject src = (AsciiSrcObject)w; 1139 1140 /* If the src is really a multi, call the multi save */ 1141 if (XtIsSubclass(w, multiSrcObjectClass )) 1142 return (_XawMultiSave(w)); 1143 1144 else if (!XtIsSubclass(w, asciiSrcObjectClass)) 1145 XtErrorMsg("bad argument", "asciiSource", "XawError", 1146 "XawAsciiSave's parameter must be an asciiSrc or multiSrc.", 1147 NULL, NULL); 1148 1149 /* 1150 * If using the string in place then there is no need to play games 1151 * to get the internal info into a readable string. 1152 */ 1153 if (src->ascii_src.use_string_in_place) 1154 return (True); 1155 1156 if (src->ascii_src.type == XawAsciiFile) { 1157#ifdef OLDXAW 1158 if (!src->ascii_src.changes) 1159#else 1160 if (!src->text_src.changed) /* No changes to save */ 1161#endif 1162 return (True); 1163 1164 if (WritePiecesToFile(src, src->ascii_src.string) == False) 1165 return (False); 1166 } 1167 else { 1168 if (src->ascii_src.allocated_string == True) 1169 XtFree(src->ascii_src.string); 1170 else 1171 src->ascii_src.allocated_string = True; 1172 1173 src->ascii_src.string = StorePiecesInString(src); 1174 } 1175#ifdef OLDXAW 1176 src->ascii_src.changes = False; 1177#else 1178 src->text_src.changed = False; 1179#endif 1180 1181 return (True); 1182} 1183 1184/* 1185 * Function: 1186 * XawAsciiSaveAsFile 1187 * 1188 * Arguments: 1189 * w - AsciiSrc widget 1190 * name - name of the file to save this file into 1191 * 1192 * Description: 1193 * Save the current buffer as a file. 1194 * 1195 * Returns: 1196 * True if the save was sucessful 1197 */ 1198Bool 1199XawAsciiSaveAsFile(Widget w, _Xconst char *name) 1200{ 1201 AsciiSrcObject src = (AsciiSrcObject)w; 1202 Bool ret; 1203 1204 /* If the src is really a multi, call the multi save */ 1205 1206 if (XtIsSubclass( w, multiSrcObjectClass)) 1207 return (_XawMultiSaveAsFile(w, name)); 1208 1209 else if (!XtIsSubclass(w, asciiSrcObjectClass)) 1210 XtErrorMsg("bad argument", "asciiSource", "XawError", 1211 "XawAsciiSaveAsFile's 1st parameter must be an " 1212 "asciiSrc or multiSrc.", 1213 NULL, NULL); 1214 1215 if (src->ascii_src.type == XawAsciiFile) 1216 ret = WritePiecesToFile(src, (String)name); 1217 else { 1218 String string = StorePiecesInString(src); 1219 1220 ret = WriteToFile(string, (String)name, src->ascii_src.length); 1221 XtFree(string); 1222 } 1223 1224 return (ret); 1225} 1226 1227/* 1228 * Function: 1229 * XawAsciiSourceChanged 1230 * 1231 * Parameters: 1232 * w - ascii source widget 1233 * 1234 * Description: 1235 * Returns true if the source has changed since last saved. 1236 * 1237 * Returns: 1238 * A Boolean (see description). 1239 */ 1240Bool 1241XawAsciiSourceChanged(Widget w) 1242{ 1243#ifdef OLDXAW 1244 if (XtIsSubclass(w, multiSrcObjectClass)) 1245 return (((MultiSrcObject)w)->multi_src.changes); 1246 1247 if (XtIsSubclass(w, asciiSrcObjectClass)) 1248 return (((AsciiSrcObject)w)->ascii_src.changes); 1249#else 1250 if (XtIsSubclass(w, textSrcObjectClass)) 1251 return (((TextSrcObject)w)->textSrc.changed); 1252#endif 1253 XtErrorMsg("bad argument", "asciiSource", "XawError", 1254 "XawAsciiSourceChanged parameter must be an " 1255 "asciiSrc or multiSrc.", 1256 NULL, NULL); 1257 1258 return (True); 1259} 1260 1261/* 1262 * Private Functions 1263 */ 1264static void 1265RemoveOldStringOrFile(AsciiSrcObject src, Bool checkString) 1266{ 1267 FreeAllPieces(src); 1268 1269 if (checkString && src->ascii_src.allocated_string) { 1270 XtFree(src->ascii_src.string); 1271 src->ascii_src.allocated_string = False; 1272 src->ascii_src.string = NULL; 1273 } 1274} 1275 1276/* 1277 * Function: 1278 * WriteToFile 1279 * 1280 * Parameters: 1281 * string - string to write 1282 * name - the name of the file 1283 * 1284 * Description: 1285 * Write the string specified to the begining of the file specified. 1286 * 1287 * Returns: 1288 * returns True if sucessful, False otherwise 1289 */ 1290static Bool 1291WriteToFile(String string, String name, unsigned length) 1292{ 1293 int fd; 1294 1295 if ((fd = creat(name, 0666)) == -1 1296 || write(fd, string, length) == -1) 1297 return (False); 1298 1299 if (close(fd) == -1) 1300 return (False); 1301 1302 return (True); 1303} 1304 1305/* 1306 * Function: 1307 * WritePiecesToFile 1308 * 1309 * Parameters: 1310 * src - ascii source object 1311 * name - name of the file 1312 * 1313 * Description: 1314 * Almost identical to WriteToFile, but only works for ascii src objects 1315 * of type XawAsciiFile. This function avoids allocating temporary memory, 1316 * what can be useful when editing very large files. 1317 * 1318 * Returns: 1319 * returns True if sucessful, False otherwise 1320 */ 1321static Bool 1322WritePiecesToFile(AsciiSrcObject src, String name) 1323{ 1324 Piece *piece; 1325 int fd; 1326 1327 if (src->ascii_src.data_compression) { 1328 Piece *tmp; 1329 1330 piece = src->ascii_src.first_piece; 1331 while (piece) { 1332 int bytes = src->ascii_src.piece_size - piece->used; 1333 1334 if (bytes > 0 && (tmp = piece->next) != NULL) { 1335 bytes = XawMin(bytes, tmp->used); 1336 memcpy(piece->text + piece->used, tmp->text, bytes); 1337 memmove(tmp->text, tmp->text + bytes, tmp->used - bytes); 1338 piece->used += bytes; 1339 if ((tmp->used -= bytes) == 0) { 1340 RemovePiece(src, tmp); 1341 continue; 1342 } 1343 } 1344 piece = piece->next; 1345 } 1346 } 1347 1348 if ((fd = creat(name, 0666)) == -1) 1349 return (False); 1350 1351 for (piece = src->ascii_src.first_piece; piece; piece = piece->next) 1352 if (write(fd, piece->text, piece->used) == -1) 1353 return (False); 1354 1355 if (close(fd) == -1) 1356 return (False); 1357 1358 return (True); 1359} 1360 1361/* 1362 * Function: 1363 * StorePiecesInString 1364 * 1365 * Parameters: 1366 * data - ascii pointer data 1367 * 1368 * Description: 1369 * Store the pieces in memory into a standard ascii string. 1370 */ 1371static String 1372StorePiecesInString(AsciiSrcObject src) 1373{ 1374 String string; 1375 XawTextPosition first; 1376 Piece *piece; 1377 1378 string = XtMalloc((unsigned)(src->ascii_src.length + 1)); 1379 1380 for (first = 0, piece = src->ascii_src.first_piece ; piece != NULL; 1381 first += piece->used, piece = piece->next) 1382 memcpy(string + first, piece->text, (unsigned)piece->used); 1383 1384 string[src->ascii_src.length] = '\0'; 1385 1386 /* 1387 * This will refill all pieces to capacity 1388 */ 1389 if (src->ascii_src.data_compression) { 1390 FreeAllPieces(src); 1391 LoadPieces(src, NULL, string); 1392 } 1393 1394 return (string); 1395} 1396 1397/* 1398 * Function: 1399 * InitStringOrFile 1400 * 1401 * Parameters: 1402 * src - AsciiSource 1403 * 1404 * Description: 1405 * Initializes the string or file. 1406 */ 1407static FILE * 1408InitStringOrFile(AsciiSrcObject src, Bool newString) 1409{ 1410 mode_t open_mode = 0; 1411 const char *fdopen_mode = NULL; 1412 int fd; 1413 FILE *file; 1414 1415 if (src->ascii_src.type == XawAsciiString) { 1416 if (src->ascii_src.string == NULL) 1417 src->ascii_src.length = 0; 1418 1419 else if (!src->ascii_src.use_string_in_place) { 1420 src->ascii_src.string = XtNewString(src->ascii_src.string); 1421 src->ascii_src.allocated_string = True; 1422 src->ascii_src.length = strlen(src->ascii_src.string); 1423 } 1424 1425 if (src->ascii_src.use_string_in_place) { 1426 if (src->ascii_src.string != NULL) 1427 src->ascii_src.length = strlen(src->ascii_src.string); 1428 /* In case the length resource is incorrectly set */ 1429 if (src->ascii_src.length > src->ascii_src.ascii_length) 1430 src->ascii_src.ascii_length = src->ascii_src.length; 1431 1432 if (src->ascii_src.ascii_length == MAGIC_VALUE) 1433 src->ascii_src.piece_size = src->ascii_src.length; 1434 else 1435 src->ascii_src.piece_size = src->ascii_src.ascii_length + 1; 1436 } 1437 1438 return (NULL); 1439 } 1440 1441 /* 1442 * type is XawAsciiFile 1443 */ 1444 src->ascii_src.is_tempfile = False; 1445 1446 switch (src->text_src.edit_mode) { 1447 case XawtextRead: 1448 if (src->ascii_src.string == NULL) 1449 XtErrorMsg("NoFile", "asciiSourceCreate", "XawError", 1450 "Creating a read only disk widget and no file specified.", 1451 NULL, NULL); 1452 open_mode = O_RDONLY; 1453 fdopen_mode = "r"; 1454 break; 1455 case XawtextAppend: 1456 case XawtextEdit: 1457 if (src->ascii_src.string == NULL) { 1458 src->ascii_src.string = "*ascii-src*"; 1459 src->ascii_src.is_tempfile = True; 1460 } 1461 else { 1462/* O_NOFOLLOW is a FreeBSD & Linux extension */ 1463#ifdef O_NOFOLLOW 1464 open_mode = O_RDWR | O_NOFOLLOW; 1465#else 1466 open_mode = O_RDWR; /* unsafe; subject to race conditions */ 1467#endif /* O_NOFOLLOW */ 1468 fdopen_mode = "r+"; 1469 } 1470 break; 1471 default: 1472 XtErrorMsg("badMode", "asciiSourceCreate", "XawError", 1473 "Bad editMode for ascii source; must be Read, " 1474 "Append or Edit.", 1475 NULL, NULL); 1476 } 1477 1478 /* If is_tempfile, allocate a private copy of the text 1479 * Unlikely to be changed, just to set allocated_string */ 1480 if (newString || src->ascii_src.is_tempfile) { 1481 src->ascii_src.string = XtNewString(src->ascii_src.string); 1482 src->ascii_src.allocated_string = True; 1483 } 1484 1485 if (!src->ascii_src.is_tempfile) { 1486 if ((fd = open(src->ascii_src.string, open_mode, 0666)) != -1) { 1487 if ((file = fdopen(fd, fdopen_mode))) { 1488 (void)fseek(file, 0, SEEK_END); 1489 src->ascii_src.length = (XawTextPosition)ftell(file); 1490 return (file); 1491 } 1492 } 1493 { 1494 String params[2]; 1495 Cardinal num_params = 2; 1496 1497 params[0] = src->ascii_src.string; 1498 params[1] = strerror(errno); 1499 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), 1500 "openError", "asciiSourceCreate", "XawWarning", 1501 "Cannot open file %s; %s", params, &num_params); 1502 } 1503 } 1504 src->ascii_src.length = 0; 1505 return (NULL); 1506} 1507 1508static void 1509LoadPieces(AsciiSrcObject src, FILE *file, char *string) 1510{ 1511 char *ptr; 1512 Piece *piece = NULL; 1513 XawTextPosition left; 1514 1515 if (string == NULL) { 1516 if (src->ascii_src.type == XawAsciiFile) { 1517 if (src->ascii_src.length != 0) { 1518 int len; 1519 1520 left = 0; 1521 fseek(file, 0, 0); 1522 while (left < src->ascii_src.length) { 1523 ptr = XtMalloc((unsigned)src->ascii_src.piece_size); 1524 if ((len = fread(ptr, (Size_t)sizeof(unsigned char), 1525 (Size_t)src->ascii_src.piece_size, file)) < 0) 1526 XtErrorMsg("readError", "asciiSourceCreate", "XawError", 1527 "fread returned error.", NULL, NULL); 1528 piece = AllocNewPiece(src, piece); 1529 piece->text = ptr; 1530 piece->used = XawMin(len, src->ascii_src.piece_size); 1531 left += piece->used; 1532 } 1533 } 1534 else { 1535 piece = AllocNewPiece(src, NULL); 1536 piece->text = XtMalloc((unsigned)src->ascii_src.piece_size); 1537 piece->used = 0; 1538 } 1539 return; 1540 } 1541 else 1542 string = src->ascii_src.string; 1543 } 1544 1545 if (src->ascii_src.use_string_in_place) { 1546 piece = AllocNewPiece(src, piece); 1547 piece->used = XawMin(src->ascii_src.length, src->ascii_src.piece_size); 1548 piece->text = src->ascii_src.string; 1549 return; 1550 } 1551 1552 ptr = string; 1553 left = src->ascii_src.length; 1554 do { 1555 piece = AllocNewPiece(src, piece); 1556 1557 piece->text = XtMalloc((unsigned)src->ascii_src.piece_size); 1558 piece->used = XawMin(left, src->ascii_src.piece_size); 1559 if (piece->used != 0) 1560 memcpy(piece->text, ptr, (unsigned)piece->used); 1561 1562 left -= piece->used; 1563 ptr += piece->used; 1564 } while (left > 0); 1565} 1566 1567/* 1568 * Function: 1569 * AllocNewPiece 1570 * 1571 * Parameters: 1572 * src - AsciiSrc Widget 1573 * prev - piece just before this one, or NULL 1574 * 1575 * Description: 1576 * Allocates a new piece of memory. 1577 * 1578 * Returns: 1579 * The allocated piece 1580 */ 1581static Piece * 1582AllocNewPiece(AsciiSrcObject src, Piece *prev) 1583{ 1584 Piece *piece = XtNew(Piece); 1585 1586 if (prev == NULL) { 1587 src->ascii_src.first_piece = piece; 1588 piece->next = NULL; 1589 } 1590 else { 1591 if (prev->next != NULL) 1592 (prev->next)->prev = piece; 1593 piece->next = prev->next; 1594 prev->next = piece; 1595 } 1596 1597 piece->prev = prev; 1598 1599 return (piece); 1600} 1601 1602/* 1603 * Function: 1604 * FreeAllPieces 1605 * 1606 * Parameters: 1607 * src - AsciiSrc Widget 1608 * 1609 * Description: 1610 * Frees all the pieces. 1611 */ 1612static void 1613FreeAllPieces(AsciiSrcObject src) 1614{ 1615 Piece *next, * first = src->ascii_src.first_piece; 1616 1617#ifdef DEBUG 1618 if (first->prev != NULL) 1619 printf("Xaw AsciiSrc Object: possible memory leak in FreeAllPieces().\n"); 1620#endif 1621 1622 for (; first != NULL ; first = next) { 1623 next = first->next; 1624 RemovePiece(src, first); 1625 } 1626} 1627 1628/* 1629 * Function: 1630 * RemovePiece 1631 * 1632 * Parameters: 1633 * piece - piece to remove 1634 * 1635 * Description: 1636 * Removes a piece from the list. 1637 */ 1638static void 1639RemovePiece(AsciiSrcObject src, Piece *piece) 1640{ 1641 if (piece->prev == NULL) 1642 src->ascii_src.first_piece = piece->next; 1643 else 1644 piece->prev->next = piece->next; 1645 1646 if (piece->next != NULL) 1647 piece->next->prev = piece->prev; 1648 1649 if (!src->ascii_src.use_string_in_place) 1650 XtFree(piece->text); 1651 1652 XtFree((char *)piece); 1653} 1654 1655/* 1656 * Function: 1657 * FindPiece 1658 * 1659 * Parameters: 1660 * src - AsciiSrc Widget 1661 * position - position that we are searching for 1662 * first - position of the first character in this piece (return) 1663 * 1664 * Description: 1665 * Finds the piece containing the position indicated. 1666 * 1667 * Returns: 1668 * the piece that contains this position 1669 */ 1670static Piece * 1671FindPiece(AsciiSrcObject src, XawTextPosition position, XawTextPosition *first) 1672{ 1673 Piece *old_piece, *piece; 1674 XawTextPosition temp; 1675 1676 for (old_piece = NULL, piece = src->ascii_src.first_piece, temp = 0; 1677 piece; old_piece = piece, piece = piece->next) 1678 if ((temp += piece->used) > position) { 1679 *first = temp - piece->used; 1680 return (piece); 1681 } 1682 1683 *first = temp - (old_piece ? old_piece->used : 0); 1684 1685 return (old_piece); /* if we run off the end the return the last piece */ 1686} 1687 1688/* 1689 * Function: 1690 * BreakPiece 1691 * 1692 * Parameters: 1693 * src - AsciiSrc Widget 1694 * piece - piece to break 1695 * 1696 * Description: 1697 * Breaks a full piece into two new pieces. 1698 */ 1699#define HALF_PIECE (src->ascii_src.piece_size >> 1) 1700static void 1701BreakPiece(AsciiSrcObject src, Piece *piece) 1702{ 1703 Piece *cnew = AllocNewPiece(src, piece); 1704 1705 cnew->text = XtMalloc((unsigned)src->ascii_src.piece_size); 1706 memcpy(cnew->text, piece->text + HALF_PIECE, 1707 (unsigned)(src->ascii_src.piece_size - HALF_PIECE)); 1708 piece->used = HALF_PIECE; 1709 cnew->used = src->ascii_src.piece_size - HALF_PIECE; 1710} 1711 1712/*ARGSUSED*/ 1713static void 1714CvtStringToAsciiType(XrmValuePtr args, Cardinal *num_args, 1715 XrmValuePtr fromVal, XrmValuePtr toVal) 1716{ 1717 static XawAsciiType type; 1718 XrmQuark q; 1719 char name[7]; 1720 1721 XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); 1722 q = XrmStringToQuark(name); 1723 1724 if (q == Qstring) 1725 type = XawAsciiString; 1726 else if (q == Qfile) 1727 type = XawAsciiFile; 1728 else { 1729 toVal->size = 0; 1730 toVal->addr = NULL; 1731 XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType); 1732 } 1733 1734 toVal->size = sizeof(XawAsciiType); 1735 toVal->addr = (XPointer)&type; 1736} 1737 1738/*ARGSUSED*/ 1739static Boolean 1740CvtAsciiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, 1741 XrmValuePtr fromVal, XrmValuePtr toVal, 1742 XtPointer *data) 1743{ 1744 static String buffer; 1745 Cardinal size; 1746 1747 switch (*(XawAsciiType *)fromVal->addr) { 1748 case XawAsciiFile: 1749 buffer = XtEfile; 1750 break; 1751 case XawAsciiString: 1752 buffer = XtEstring; 1753 break; 1754 default: 1755 XawTypeToStringWarning(dpy, XtRAsciiType); 1756 toVal->addr = NULL; 1757 toVal->size = 0; 1758 return (False); 1759 } 1760 1761 size = strlen(buffer) + 1; 1762 if (toVal->addr != NULL) { 1763 if (toVal->size < size) { 1764 toVal->size = size; 1765 return (False); 1766 } 1767 strcpy((char *)toVal->addr, buffer); 1768 } 1769 else 1770 toVal->addr = (XPointer)buffer; 1771 toVal->size = sizeof(String); 1772 1773 return (True); 1774} 1775 1776/*ARGSUSED*/ 1777static void 1778GetDefaultPieceSize(Widget w, int offset, XrmValue *value) 1779{ 1780 static XPointer pagesize; 1781 1782 if (pagesize == NULL) { 1783 pagesize = (XPointer)((long)_XawGetPageSize()); 1784 if (pagesize < (XPointer)BUFSIZ) 1785 pagesize = (XPointer)BUFSIZ; 1786 } 1787 1788 value->addr = (XPointer)&pagesize; 1789} 1790 1791#if (defined(ASCII_STRING) || defined(ASCII_DISK)) 1792# include <X11/Xaw/Cardinals.h> 1793#endif 1794 1795#ifdef ASCII_STRING 1796/* 1797 * Compatability functions. 1798 */ 1799/* 1800 * Function: 1801 * AsciiStringSourceCreate 1802 * 1803 * Parameters: 1804 * parent - widget that will own this source 1805 * args - the argument list 1806 * num_args - "" 1807 * 1808 * Description: 1809 * Creates a string source. 1810 * 1811 * Returns: 1812 * A pointer to the new text source. 1813 */ 1814Widget 1815XawStringSourceCreate(Widget parent, ArgList args, Cardinal num_args) 1816{ 1817 XawTextSource src; 1818 ArgList ascii_args; 1819 Arg temp[2]; 1820 1821 XtSetArg(temp[0], XtNtype, XawAsciiString); 1822 XtSetArg(temp[1], XtNuseStringInPlace, True); 1823 ascii_args = XtMergeArgLists(temp, TWO, args, num_args); 1824 1825 src = XtCreateWidget("genericAsciiString", asciiSrcObjectClass, parent, 1826 ascii_args, num_args + TWO); 1827 XtFree((char *)ascii_args); 1828 1829 return (src); 1830} 1831 1832/* 1833 * This is hacked up to try to emulate old functionality, it 1834 * may not work, as I have not old code to test it on. 1835 * 1836 * Chris D. Peterson 8/31/89. 1837 */ 1838void 1839XawTextSetLastPos(Widget w, XawTextPosition lastPos) 1840{ 1841 AsciiSrcObject src = (AsciiSrcObject)XawTextGetSource(w); 1842 1843 src->ascii_src.piece_size = lastPos; 1844} 1845#endif /* ASCII_STRING */ 1846 1847#ifdef ASCII_DISK 1848/* 1849 * Function: 1850 * AsciiDiskSourceCreate 1851 * 1852 * Parameters: 1853 * parent - widget that will own this source 1854 * args - argument list 1855 * num_args - "" 1856 * 1857 * Description: 1858 * Creates a disk source. 1859 * 1860 * Returns: 1861 * A pointer to the new text source 1862 */ 1863Widget 1864XawDiskSourceCreate(Widget parent, ArgList args, Cardinal num_args) 1865{ 1866 XawTextSource src; 1867 ArgList ascii_args; 1868 Arg temp[1]; 1869 int i; 1870 1871 XtSetArg(temp[0], XtNtype, XawAsciiFile); 1872 ascii_args = XtMergeArgLists(temp, ONE, args, num_args); 1873 num_args++; 1874 1875 for (i = 0; i < num_args; i++) 1876 if (streq(ascii_args[i].name, XtNfile) 1877 || streq(ascii_args[i].name, XtCFile)) 1878 ascii_args[i].name = XtNstring; 1879 1880 src = XtCreateWidget("genericAsciiDisk", asciiSrcObjectClass, parent, 1881 ascii_args, num_args); 1882 XtFree((char *)ascii_args); 1883 1884 return (src); 1885} 1886#endif /* ASCII_DISK */ 1887