2 * Copyright 1991 by OMRON Corporation
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name OMRON not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. OMRON makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
22 * Authors: Chris Peterson MIT X Consortium
23 * Li Yuhong OMRON Corporation
24 * Frank Sheeran OMRON Corporation
26 * Much code taken from X11R3 String and Disk Sources.
31 Copyright 1991, 1994, 1998 The Open Group
33 Permission to use, copy, modify, distribute, and sell this software and its
34 documentation for any purpose is hereby granted without fee, provided that
35 the above copyright notice appear in all copies and that both that
36 copyright notice and this permission notice appear in supporting
39 The above copyright notice and this permission notice shall be included in
40 all copies or substantial portions of the Software.
42 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
46 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
47 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 Except as contained in this notice, the name of The Open Group shall not be
50 used in advertising or otherwise to promote the sale, use or other dealings
51 in this Software without prior written authorization from The Open Group.
62 #include <X11/IntrinsicP.h>
63 #include <X11/StringDefs.h>
64 #include <X11/Xfuncs.h>
66 #include <X11/Xmu/CharSet.h>
67 #include <X11/Xmu/Misc.h>
68 #include <X11/Xaw/XawInit.h>
69 #include <X11/Xaw/MultiSrcP.h>
70 #include <X11/Xaw/XawImP.h>
74 #include <sys/types.h>
78 #define MAGIC_VALUE ((XawTextPosition)-1)
79 #define streq(a, b) (strcmp((a), (b)) == 0)
83 #define Size_t unsigned int
93 static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int);
94 static int ReplaceText(Widget, XawTextPosition, XawTextPosition,
96 static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType,
97 XawTextScanDirection, int, Bool);
98 static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection,
100 static void XawMultiSrcClassInitialize(void);
101 static void XawMultiSrcDestroy(Widget);
102 static void XawMultiSrcInitialize(Widget, Widget, ArgList, Cardinal*);
103 static Boolean XawMultiSrcSetValues(Widget, Widget, Widget,
105 static void XawMultiSrcGetValuesHook(Widget, ArgList, Cardinal*);
110 static MultiPiece *AllocNewPiece(MultiSrcObject, MultiPiece*);
111 static void BreakPiece(MultiSrcObject, MultiPiece*);
112 static Boolean CvtMultiTypeToString(Display*, XrmValuePtr, Cardinal*,
113 XrmValuePtr, XrmValuePtr, XtPointer*);
114 static void CvtStringToMultiType(XrmValuePtr, Cardinal*,
115 XrmValuePtr, XrmValuePtr);
116 static MultiPiece *FindPiece(MultiSrcObject, XawTextPosition,
118 static void FreeAllPieces(MultiSrcObject);
119 static FILE *InitStringOrFile(MultiSrcObject, Bool);
120 static void LoadPieces(MultiSrcObject, FILE*, char*);
121 static void RemovePiece(MultiSrcObject, MultiPiece*);
122 static void RemoveOldStringOrFile(MultiSrcObject, Bool);
123 static String StorePiecesInString(MultiSrcObject);
124 static Bool WriteToFile(String, String);
125 static void GetDefaultPieceSize(Widget, int, XrmValue*);
130 #define offset(field) XtOffsetOf(MultiSrcRec, multi_src.field)
131 static XtResource resources[] = {
145 sizeof(XawAsciiType),
148 (XtPointer)XawAsciiString
155 offset(data_compression),
163 sizeof(XawTextPosition),
166 (XtPointer)GetDefaultPieceSize
184 offset(use_string_in_place),
193 offset(multi_length),
195 (XtPointer)MAGIC_VALUE
200 #define superclass (&textSrcClassRec)
201 MultiSrcClassRec multiSrcClassRec = {
204 (WidgetClass)superclass, /* superclass */
205 "MultiSrc", /* class_name */
206 sizeof(MultiSrcRec), /* widget_size */
207 XawMultiSrcClassInitialize, /* class_initialize */
208 NULL, /* class_part_initialize */
209 False, /* class_inited */
210 XawMultiSrcInitialize, /* initialize */
211 NULL, /* initialize_hook */
215 resources, /* resources */
216 XtNumber(resources), /* num_resources */
217 NULLQUARK, /* xrm_class */
222 XawMultiSrcDestroy, /* destroy */
225 XawMultiSrcSetValues, /* set_values */
226 NULL, /* set_values_hook */
228 XawMultiSrcGetValuesHook, /* get_values_hook */
230 XtVersion, /* version */
231 NULL, /* callback_private */
235 NULL, /* extension */
240 ReplaceText, /* Replace */
243 XtInheritSetSelection, /* SetSelection */
244 XtInheritConvertSelection, /* ConvertSelection */
248 NULL, /* extension */
252 WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec;
254 static XrmQuark Qstring, Qfile;
260 XawMultiSrcClassInitialize(void)
262 XawInitializeWidgetSet();
263 Qstring = XrmPermStringToQuark(XtEstring);
264 Qfile = XrmPermStringToQuark(XtEfile);
265 XtAddConverter(XtRString, XtRMultiType, CvtStringToMultiType, NULL, 0);
266 XtSetTypeConverter(XtRMultiType, XtRString, CvtMultiTypeToString, NULL, 0,
272 * XawMultiSrcInitialize
275 * request - widget requested by the argument list
276 * cnew - the new widget with both resource and non resource values
278 * num_args - (unused)
281 * Initializes the multi src object
285 XawMultiSrcInitialize(Widget request, Widget cnew,
286 ArgList args, Cardinal *num_args)
288 MultiSrcObject src = (MultiSrcObject)cnew;
292 * Set correct flags (override resources) depending upon widget class
295 src->multi_src.changes = False;
297 src->text_src.changed = False;
299 src->multi_src.allocated_string = False;
301 if (src->multi_src.use_string_in_place && src->multi_src.string == NULL)
302 src->multi_src.use_string_in_place = False;
304 file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile);
305 LoadPieces(src, file, NULL);
309 src->text_src.text_format = XawFmtWide;
317 * w - MultiSource object
318 * pos - position of the text to retrieve
319 * text - text block that will contain returned text
320 * length - maximum number of characters to read
323 * This function reads the source.
326 * The character position following the retrieved text.
328 static XawTextPosition
329 ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length)
331 MultiSrcObject src = (MultiSrcObject)w;
332 XawTextPosition count, start;
333 MultiPiece *piece = FindPiece(src, pos, &start);
335 text->format = XawFmtWide;
336 text->firstPos = pos;
337 text->ptr = (char *)(piece->text + (pos - start));
338 count = piece->used - (pos - start);
339 text->length = Max(0, (length > count) ? count : length);
341 return (pos + text->length);
349 * w - MultiSource object
350 * startPos - ends of text that will be removed
352 * text - new text to be inserted into buffer at startPos
355 * Replaces a block of text with new text.
358 * XawEditDone on success, XawEditError otherwise
362 ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos,
363 XawTextBlock *u_text_p)
365 MultiSrcObject src = (MultiSrcObject)w;
366 MultiPiece *start_piece, *end_piece, *temp_piece;
367 XawTextPosition start_first, end_first;
368 int length, firstPos;
370 Bool local_artificial_block = False;
373 /* STEP 1: The user handed me a text block called `u_text' that may be
374 * in either FMTWIDE or FMT8BIT (ie MB.) Later code needs the block
375 * `text' to hold FMTWIDE. So, this copies `u_text' to `text', and if
376 * `u_text' was MB, I knock it up to WIDE
378 if (u_text_p->length == 0) /* if so, the block contents never ref'd */
381 else if (u_text_p->format == XawFmtWide) {
382 local_artificial_block = False; /* don't have to free it ourselves */
383 text.firstPos = u_text_p->firstPos;
384 text.length = u_text_p->length;
385 text.ptr = u_text_p->ptr;
389 * WARNING! u_text->firstPos and length are in units of CHAR,
392 local_artificial_block = True; /* have to free it ourselves */
394 text.length = u_text_p->length; /* _XawTextMBToWC converts this
398 text.ptr = (char*)_XawTextMBToWC(XtDisplay(XtParent(w)),
399 &u_text_p->ptr[u_text_p->firstPos],
402 /* I assert the following assignment is not needed - since Step 4
403 depends on length, it has no need of a terminating NULL. I think
404 the ASCII-version has the same needless NULL. */
405 /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/
408 /* STEP 2: some initialization... */
409 if (src->text_src.edit_mode == XawtextRead)
410 return (XawEditError);
412 start_piece = FindPiece(src, startPos, &start_first);
413 end_piece = FindPiece(src, endPos, &end_first);
415 /* STEP 3: remove the empty pieces... */
416 if (start_piece != end_piece) {
417 temp_piece = start_piece->next;
419 /* If empty and not the only piece then remove it */
420 if (((start_piece->used = startPos - start_first) == 0)
421 && !(start_piece->next == NULL && start_piece->prev == NULL))
422 RemovePiece(src, start_piece);
424 while (temp_piece != end_piece) {
425 temp_piece = temp_piece->next;
426 RemovePiece(src, temp_piece->prev);
428 end_piece->used -= endPos - end_first;
429 if (end_piece->used != 0)
430 memmove(end_piece->text, end_piece->text + endPos - end_first,
431 end_piece->used * sizeof(wchar_t));
433 else { /* We are fully in one piece */
434 if ((start_piece->used -= endPos - startPos) == 0) {
435 if (!(start_piece->next == NULL && start_piece->prev == NULL))
436 RemovePiece(src, start_piece);
439 memmove(start_piece->text + (startPos - start_first),
440 start_piece->text + (endPos - start_first),
441 (start_piece->used - (startPos - start_first)) *
443 if (src->multi_src.use_string_in_place &&
444 ((src->multi_src.length - (endPos - startPos))
445 < src->multi_src.piece_size - 1))
446 start_piece->text[src->multi_src.length - (endPos - startPos)] =
451 src->multi_src.length += text.length -(endPos - startPos);
453 /* STEP 4: insert the new stuff */
454 if ( text.length != 0) {
455 start_piece = FindPiece(src, startPos, &start_first);
456 length = text.length;
457 firstPos = text.firstPos;
463 if (src->multi_src.use_string_in_place) {
464 if (start_piece->used == src->multi_src.piece_size - 1) {
467 * The string is used in place, then the string
468 * is not allowed to grow
470 start_piece->used = src->multi_src.length =
471 src->multi_src.piece_size - 1;
473 start_piece->text[src->multi_src.length] = (wchar_t)0;
474 return (XawEditError);
478 if (start_piece->used == src->multi_src.piece_size) {
479 BreakPiece(src, start_piece);
480 start_piece = FindPiece(src, startPos, &start_first);
483 fill = Min((int)(src->multi_src.piece_size - start_piece->used), length);
485 ptr = start_piece->text + (startPos - start_first);
486 memmove(ptr + fill, ptr, (start_piece->used -
487 (startPos - start_first)) * sizeof(wchar_t));
488 wptr =(wchar_t *)text.ptr;
489 (void)wcsncpy(ptr, wptr + firstPos, fill);
493 start_piece->used += fill;
498 if (local_artificial_block == True)
499 /* In other words, text is not the u_text that the user handed me but
500 one I made myself. I only care, because I need to free the string */
503 if (src->multi_src.use_string_in_place)
504 start_piece->text[start_piece->used] = (wchar_t)0;
507 src->multi_src.changes = True;
508 XtCallCallbacks(w, XtNcallback, NULL);
511 return (XawEditDone);
519 * w - MultiSource widget
520 * position - position to start scanning
521 * type - type of thing to scan for
522 * dir - direction to scan
523 * count - which occurance if this thing to search for
524 * include - whether or not to include the character found in
525 * the position that is returned
528 * Scans the text source for the number and type of item specified.
531 * The position of the item found
534 * While there are only 'n' characters in the file there are n+1
535 * possible cursor positions (one before the first character and
536 * one after the last character
538 static XawTextPosition
539 Scan(Widget w, register XawTextPosition position, XawTextScanType type,
540 XawTextScanDirection dir, int count, Bool include)
542 MultiSrcObject src = (MultiSrcObject)w;
545 XawTextPosition first, first_eol_position = position;
546 register wchar_t *ptr;
549 if (type == XawstAll) {
550 if (dir == XawsdRight)
551 return (src->multi_src.length);
555 /* STEP 1: basic sanity checks */
556 if (position > src->multi_src.length)
557 position = src->multi_src.length;
559 if (dir == XawsdRight) {
560 if (position == src->multi_src.length)
561 return (src->multi_src.length);
571 piece = FindPiece(src, position, &first);
573 if (piece->used == 0)
576 ptr = (position - first) + piece->text;
581 case XawstWhiteSpace:
582 case XawstAlphaNumeric:
583 for (; cnt > 0 ; cnt--) {
584 Bool non_space = False, first_eol = True;
590 if (ptr < piece->text) {
592 if (piece == NULL) /* Begining of text */
594 ptr = piece->text + piece->used - 1;
597 else if (ptr >= piece->text + piece->used) {
599 if (piece == NULL) /* End of text */
600 return (src->multi_src.length);
608 if (type == XawstAlphaNumeric) {
616 else if (type == XawstWhiteSpace) {
624 else if (type == XawstEOL) {
625 if (c == _Xaw_atowc(XawLF))
628 else { /* XawstParagraph */
630 if (c == _Xaw_atowc(XawLF)) {
631 first_eol_position = position;
636 if (c == _Xaw_atowc(XawLF))
638 else if (!iswspace(c))
644 if (type == XawstParagraph)
645 position = first_eol_position;
651 position += count * inc;
657 if (dir == XawsdLeft)
660 if (position >= src->multi_src.length)
661 return (src->multi_src.length);
673 * w - MultiSource objecy
674 * position - position to start scanning
675 * dir - direction to scan
676 * text - text block to search for
679 * Searchs the text source for the text block passed.
682 * The position of the item found
684 static XawTextPosition
685 Search(Widget w, register XawTextPosition position, XawTextScanDirection dir,
688 MultiSrcObject src = (MultiSrcObject)w;
689 register int count = 0;
693 Display *d = XtDisplay(XtParent(w));
696 XawTextPosition first;
700 /* STEP 1: First, a brief sanity check */
701 if (dir == XawsdRight)
706 return (XawTextSearchError);
710 /* STEP 2: Ensure I have a local wide string.. */
712 /* Since this widget stores 32bit chars, I check here to see if
713 I'm being passed a string claiming to be 8bit chars (ie, MB text.)
714 If that is the case, naturally I convert to 32bit format */
716 /*if the block was FMT8BIT, length will convert to REAL wchar count bellow */
717 wtarget_len = text->length;
719 if (text->format == XawFmtWide)
720 wtarget = &(((wchar_t*)text->ptr) [text->firstPos]);
722 /* The following converts wtarget_len from byte len to wchar count */
723 wtarget = _XawTextMBToWC(d, &text->ptr[text->firstPos], &wtarget_len);
726 /* OK, I can now assert that wtarget holds wide characters, wtarget_len
727 holds an accurate count of those characters, and that firstPos has been
728 effectively factored out of the following computations */
730 /* STEP 3: SEARCH! */
731 buf = (wchar_t *)XtMalloc(sizeof(wchar_t) * wtarget_len);
732 (void)wcsncpy(buf, wtarget, wtarget_len);
733 piece = FindPiece(src, position, &first);
734 ptr = (position - first) + piece->text;
738 if (*ptr == (dir == XawsdRight ? *(buf + count)
739 : *(buf + wtarget_len - count - 1))) {
740 if (count == text->length - 1)
747 position -=inc * count;
756 while (ptr < piece->text) {
757 cnt = piece->text - ptr;
760 if (piece == NULL) { /* Begining of text */
762 return (XawTextSearchError);
764 ptr = piece->text + piece->used - cnt;
767 while (ptr >= piece->text + piece->used) {
768 cnt = ptr - (piece->text + piece->used);
771 if (piece == NULL) { /* End of text */
773 return (XawTextSearchError);
775 ptr = piece->text + cnt;
780 if (dir == XawsdLeft)
783 return(position - (wtarget_len - 1));
788 * XawMultiSrcSetValues
791 * current - current state of the widget
792 * request - what was requested
793 * cnew - what the widget will become
794 * args - representation of resources that have changed
795 * num_args - number of changed resources
798 * Sets the values for the MultiSource.
801 * True if redisplay is needed
804 XawMultiSrcSetValues(Widget current, Widget request, Widget cnew,
805 ArgList args, Cardinal *num_args)
807 MultiSrcObject src = (MultiSrcObject)cnew;
808 MultiSrcObject old_src = (MultiSrcObject)current;
809 XtAppContext app_con = XtWidgetToApplicationContext(cnew);
810 Bool total_reset = False, string_set = False;
814 if (old_src->multi_src.use_string_in_place
815 != src->multi_src.use_string_in_place) {
816 XtAppWarning(app_con,
817 "MultiSrc: The XtNuseStringInPlace resources "
818 "may not be changed.");
819 src->multi_src.use_string_in_place =
820 old_src->multi_src.use_string_in_place;
823 for (i = 0; i < *num_args ; i++)
824 if (streq(args[i].name, XtNstring)) {
829 if (string_set || old_src->multi_src.type != src->multi_src.type) {
830 RemoveOldStringOrFile(old_src, string_set);
831 src->multi_src.allocated_string = old_src->multi_src.allocated_string;
832 file = InitStringOrFile(src, string_set);
834 LoadPieces(src, file, NULL);
838 for (i = 0; i < src->text_src.num_text; i++)
839 /* Tell text widget what happened */
840 XawTextSetSource(src->text_src.text[i], cnew, 0);
842 XawTextSetSource(XtParent(cnew), cnew, 0);
847 if (old_src->multi_src.multi_length != src->multi_src.multi_length)
848 src->multi_src.piece_size = src->multi_src.multi_length + 1;
850 if ( !total_reset && old_src->multi_src.piece_size
851 != src->multi_src.piece_size) {
852 String mb_string = StorePiecesInString(old_src);
854 if (mb_string != 0) {
855 FreeAllPieces(old_src);
856 LoadPieces(src, NULL, mb_string);
860 /* If the buffer holds bad chars, don't touch it... */
861 XtAppWarningMsg(app_con,
862 "convertError", "multiSource", "XawError",
863 XtName(XtParent((Widget)old_src)), NULL, NULL);
864 XtAppWarningMsg(app_con,
865 "convertError", "multiSource", "XawError",
866 "Non-character code(s) in buffer.", NULL, NULL);
874 XawMultiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
876 MultiSrcObject src = (MultiSrcObject)w;
879 if (src->multi_src.type == XawAsciiString) {
880 for (i = 0; i < *num_args ; i++) {
881 if (streq(args[i].name, XtNstring)) {
882 if (src->multi_src.use_string_in_place)
883 *((char **)args[i].value) = (char *)
884 src->multi_src.first_piece->text;
885 else if (_XawMultiSave(w)) /* If save sucessful */
886 *((char **)args[i].value) = (char *)src->multi_src.string;
894 XawMultiSrcDestroy(Widget w)
896 RemoveOldStringOrFile((MultiSrcObject) w, True);
904 * XawMultiSourceFreeString
907 * w - MultiSrc widget
910 * Frees the string returned by a get values call
911 * on the string when the source is of type string.
914 * The public interface is XawAsciiSourceFreeString!
917 _XawMultiSourceFreeString(Widget w)
919 MultiSrcObject src = (MultiSrcObject)w;
921 if (src->multi_src.allocated_string) {
922 XtFree((char *)src->multi_src.string);
923 src->multi_src.allocated_string = False;
924 src->multi_src.string = NULL;
933 * w - multiSrc Widget
936 * Saves all the pieces into a file or string as required.
939 * True if the save was successful
942 * The public interface is XawAsciiSave(w)!
945 _XawMultiSave(Widget w)
947 MultiSrcObject src = (MultiSrcObject)w;
948 XtAppContext app_con = XtWidgetToApplicationContext(w);
952 * If using the string in place then there is no need to play games
953 * to get the internal info into a readable string
955 if (src->multi_src.use_string_in_place)
958 if (src->multi_src.type == XawAsciiFile) {
960 if (!src->multi_src.changes)
962 if (!src->text_src.changed) /* No changes to save */
966 mb_string = StorePiecesInString(src);
968 if (mb_string != 0) {
969 if (WriteToFile(mb_string, (String)src->multi_src.string) == False) {
975 src->text_src.changed = False;
977 src->multi_src.changes = False;
982 /* If the buffer holds bad chars, don't touch it... */
983 XtAppWarningMsg(app_con,
984 "convertError", "multiSource", "XawError",
985 "Due to illegal characters, file not saved.",
991 /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED? The manual
992 says this routine's only function is to save files to
994 mb_string = StorePiecesInString(src);
996 if (mb_string == 0) {
997 /* If the buffer holds bad chars, don't touch it... */
998 XtAppWarningMsg(app_con,
999 "convertError", "multiSource", "XawError",
1000 XtName(XtParent((Widget)src)), NULL, NULL);
1004 /* assert: mb_string holds good characters so the buffer is fine */
1005 if (src->multi_src.allocated_string == True)
1006 XtFree((char *)src->multi_src.string);
1008 src->multi_src.allocated_string = True;
1010 src->multi_src.string = mb_string;
1013 src->multi_src.changes = False;
1015 src->text_src.changed = False;
1023 * XawMultiSaveAsFile
1026 * w - MultiSrc widget
1027 * name - name of the file to save this file into
1030 * Save the current buffer as a file.
1033 * True if the save was sucessful
1036 * The public interface is XawAsciiSaveAsFile!
1039 _XawMultiSaveAsFile(Widget w, _Xconst char* name)
1041 MultiSrcObject src = (MultiSrcObject)w;
1045 mb_string = StorePiecesInString(src);
1047 if (mb_string != 0) {
1048 ret = WriteToFile(mb_string, (char *)name);
1054 /* otherwise there was a conversion error. So print widget name too */
1055 XtAppWarningMsg(XtWidgetToApplicationContext(w),
1056 "convertError", "multiSource", "XawError",
1057 XtName(XtParent(w)), NULL, NULL);
1066 RemoveOldStringOrFile(MultiSrcObject src, Bool checkString)
1070 if (checkString && src->multi_src.allocated_string) {
1071 XtFree((char *)src->multi_src.string);
1072 src->multi_src.allocated_string = False;
1073 src->multi_src.string = NULL;
1082 * string - string to write
1083 * name - name of the file
1086 * Write the string specified to the begining of the file specified.
1089 * Returns True if sucessful, False otherwise
1092 WriteToFile(String string, String name)
1096 if (((fd = creat(name, 0666)) == -1)
1097 || (write(fd, string, strlen(string)) == -1))
1100 if (close(fd) == -1)
1109 * StorePiecesInString
1112 * src - the multiSrc object to gather data from
1115 * Store the pieces in memory into a char string.
1118 * mb_string: Caller must free
1120 * NULL: conversion error
1123 StorePiecesInString(MultiSrcObject src)
1127 int char_count = src->multi_src.length;
1128 XawTextPosition first;
1131 /* I believe the char_count + 1 and the NULL termination are unneeded! FS */
1132 wc_string = (wchar_t*)XtMalloc((char_count + 1) * sizeof(wchar_t));
1134 for (first = 0, piece = src->multi_src.first_piece ; piece != NULL;
1135 first += piece->used, piece = piece->next)
1136 (void)wcsncpy(wc_string + first, piece->text, piece->used);
1138 wc_string[char_count] = 0;
1140 /* This will refill all pieces to capacity */
1141 if (src->multi_src.data_compression) {
1143 LoadPieces(src, NULL, (char *)wc_string);
1146 /* Lastly, convert it to a MB format and send it back */
1147 mb_string = _XawTextWCToMB(XtDisplayOfObject((Widget)src),
1148 wc_string, &char_count);
1150 /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED */
1151 XtFree((char*)wc_string);
1164 * Initializes the string or file.
1167 InitStringOrFile(MultiSrcObject src, Bool newString)
1169 mode_t open_mode = 0;
1170 const char *fdopen_mode = NULL;
1173 Display *d = XtDisplayOfObject((Widget)src);
1175 if (src->multi_src.type == XawAsciiString) {
1176 if (src->multi_src.string == NULL)
1177 src->multi_src.length = 0;
1179 else if (!src->multi_src.use_string_in_place) {
1181 String temp = XtNewString((char *)src->multi_src.string);
1183 if (src->multi_src.allocated_string)
1184 XtFree((char *)src->multi_src.string);
1185 src->multi_src.allocated_string = True;
1186 src->multi_src.string = temp;
1188 length = strlen((char *)src->multi_src.string);
1190 /* Wasteful, throwing away the WC string, but need side effect! */
1191 (void)_XawTextMBToWC(d, (char *)src->multi_src.string, &length);
1192 src->multi_src.length = (XawTextPosition)length;
1195 src->multi_src.length = strlen((char *)src->multi_src.string);
1196 /* In case the length resource is incorrectly set */
1197 if (src->multi_src.length > src->multi_src.multi_length)
1198 src->multi_src.multi_length = src->multi_src.length;
1200 if (src->multi_src.multi_length == MAGIC_VALUE)
1201 src->multi_src.piece_size = src->multi_src.length;
1203 src->multi_src.piece_size = src->multi_src.multi_length + 1;
1210 * type is XawAsciiFile
1212 src->multi_src.is_tempfile = False;
1214 switch (src->text_src.edit_mode) {
1216 if (src->multi_src.string == NULL)
1217 XtErrorMsg("NoFile", "multiSourceCreate", "XawError",
1218 "Creating a read only disk widget and no file specified.",
1220 open_mode = O_RDONLY;
1225 if (src->multi_src.string == NULL) {
1226 src->multi_src.string = "*multi-src*";
1227 src->multi_src.is_tempfile = True;
1230 /* O_NOFOLLOW is a BSD & Linux extension */
1232 open_mode = O_RDWR | O_NOFOLLOW;
1234 open_mode = O_RDWR; /* unsafe; subject to race conditions */
1240 XtErrorMsg("badMode", "multiSourceCreate", "XawError",
1241 "Bad editMode for multi source; must be "
1242 "Read, Append or Edit.", NULL, NULL);
1245 /* If is_tempfile, allocate a private copy of the text
1246 * Unlikely to be changed, just to set allocated_string */
1247 if (newString || src->multi_src.is_tempfile) {
1248 String temp = XtNewString((char *)src->multi_src.string);
1250 if (src->multi_src.allocated_string)
1251 XtFree((char *)src->multi_src.string);
1252 src->multi_src.string = temp;
1253 src->multi_src.allocated_string = True;
1256 if (!src->multi_src.is_tempfile) {
1257 if ((fd = open((char *)src->multi_src.string, open_mode, 0666)) != -1) {
1258 if ((file = fdopen(fd, fdopen_mode)) != NULL) {
1259 (void)fseek(file, 0, SEEK_END);
1260 src->multi_src.length = (XawTextPosition)ftell(file);
1266 Cardinal num_params = 2;
1268 params[0] = (String)src->multi_src.string;
1269 params[1] = strerror(errno);
1270 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
1271 "openError", "multiSourceCreate", "XawWarning",
1272 "Cannot open file %s; %s", params, &num_params);
1275 src->multi_src.length = 0;
1279 /* LoadPieces: This routine takes either the MB contents of open file
1280 `file' or the MB contents of string or the MB contents of
1281 src->multi_src.string and places them in Pieces in WC format.
1283 CAUTION: You must have src->multi_src.length set to file length bytes
1284 when src->multi_src.type == XawAsciiFile. src->multi_src.length must be
1285 the length of the parameter string if string is non-NULL
1288 LoadPieces(MultiSrcObject src, FILE *file, char *string)
1290 Display *d = XtDisplayOfObject((Widget)src);
1291 wchar_t* local_str, *ptr;
1292 MultiPiece* piece = NULL;
1293 XawTextPosition left;
1294 int bytes = sizeof(wchar_t);
1295 char* temp_mb_holder = NULL;
1298 * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg
1299 * in as MB length, out as WC length. We want local_length to be
1302 int local_length = src->multi_src.length;
1304 if (string != NULL) {
1306 * ASSERT: IF our caller passed a non-null string, THEN
1307 * src->multi_src.length is currently string's * byte count,
1308 * AND string is in a MB format
1310 local_str = _XawTextMBToWC(d, (char *)string, &local_length);
1311 src->multi_src.length = (XawTextPosition) local_length;
1313 else if (src->multi_src.type != XawAsciiFile) {
1315 * here, we are not changing the contents, just reloading,
1316 * so don't change len...
1318 local_length = src->multi_src.string ?
1319 strlen((char *)src->multi_src.string) : 0;
1320 local_str = _XawTextMBToWC(d, (char *)src->multi_src.string,
1324 if (src->multi_src.length != 0) {
1326 XtMalloc((src->multi_src.length + 1) * sizeof(unsigned char));
1328 src->multi_src.length = fread(temp_mb_holder,
1329 (Size_t)sizeof(unsigned char),
1330 (Size_t)src->multi_src.length, file);
1331 if (src->multi_src.length <= 0)
1332 XtAppErrorMsg(XtWidgetToApplicationContext ((Widget) src),
1333 "readError", "multiSource", "XawError",
1334 "fread returned error.", NULL, NULL);
1335 local_length = src->multi_src.length;
1336 local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length);
1337 src->multi_src.length = local_length;
1339 if (local_str == 0) {
1341 Cardinal num_params;
1342 static char err_text[] =
1343 "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>";
1345 params[0] = XtName(XtParent((Widget)src));
1346 params[1] = src->multi_src.string;
1349 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
1350 "readLocaleError", "multiSource", "XawError",
1351 "%s: The file `%s' contains characters "
1352 "not representable in this locale.",
1353 params, &num_params);
1354 src->multi_src.length = sizeof err_text;
1355 local_length = src->multi_src.length;
1356 local_str = _XawTextMBToWC(d, err_text, &local_length);
1357 src->multi_src.length = local_length;
1361 /* ASSERT that since following while loop looks at local_length
1362 this isn't needed. Sheeran, Omron KK, 1993/07/15
1363 temp_mb_holder[src->multi_src.length] = '\0'; */
1364 local_str = (wchar_t*)temp_mb_holder;
1367 if (src->multi_src.use_string_in_place) {
1368 piece = AllocNewPiece(src, piece);
1369 piece->used = Min(src->multi_src.length, src->multi_src.piece_size);
1370 piece->text = (wchar_t*)src->multi_src.string;
1375 left = local_length;
1378 piece = AllocNewPiece(src, piece);
1380 piece->text = (wchar_t*)XtMalloc((unsigned)(src->multi_src.piece_size
1382 piece->used = Min(left, src->multi_src.piece_size);
1383 if (piece->used != 0)
1384 (void)wcsncpy(piece->text, ptr, piece->used);
1386 left -= piece->used;
1391 XtFree((char*)temp_mb_holder);
1399 * src - MultiSrc Widget
1400 * prev - the piece just before this one, or NULL
1403 * Allocates a new piece of memory.
1406 * The allocated piece
1409 AllocNewPiece(MultiSrcObject src, MultiPiece *prev)
1411 MultiPiece *piece = XtNew(MultiPiece);
1414 src->multi_src.first_piece = piece;
1418 if (prev->next != NULL)
1419 (prev->next)->prev = piece;
1420 piece->next = prev->next;
1434 * src - MultiSrc Widget
1437 * Frees all the pieces
1440 FreeAllPieces(MultiSrcObject src)
1442 MultiPiece *next, *first = src->multi_src.first_piece;
1445 if (first->prev != NULL)
1446 printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n");
1449 for (; first != NULL ; first = next) {
1451 RemovePiece(src, first);
1460 * piece - piece to remove
1463 * Removes a piece from the list.
1466 RemovePiece(MultiSrcObject src, MultiPiece *piece)
1468 if (piece->prev == NULL)
1469 src->multi_src.first_piece = piece->next;
1471 piece->prev->next = piece->next;
1473 if (piece->next != NULL)
1474 piece->next->prev = piece->prev;
1476 if (!src->multi_src.use_string_in_place)
1477 XtFree((char *)piece->text);
1479 XtFree((char *)piece);
1487 * src - MultiSrc Widget
1488 * position - position that we are searching for
1489 * first - position of the first character in this piece (return)
1492 * Finds the piece containing the position indicated.
1495 * Piece that contains this position
1498 FindPiece(MultiSrcObject src, XawTextPosition position, XawTextPosition *first)
1500 MultiPiece *old_piece, *piece;
1501 XawTextPosition temp;
1503 for (old_piece = NULL, piece = src->multi_src.first_piece, temp = 0;
1504 piece; old_piece = piece, piece = piece->next)
1505 if ((temp += piece->used) > position) {
1506 *first = temp - piece->used;
1510 *first = temp - (old_piece ? old_piece->used : 0);
1512 return (old_piece); /* if we run off the end the return the last piece */
1520 * src - MultiSrc Widget
1521 * piece - piece to break
1524 * Breaks a full piece into two new pieces.
1526 #define HALF_PIECE (src->multi_src.piece_size >> 1)
1528 BreakPiece(MultiSrcObject src, MultiPiece *piece)
1530 MultiPiece *cnew = AllocNewPiece(src, piece);
1532 cnew->text = (wchar_t *)
1533 XtMalloc(src->multi_src.piece_size * sizeof(wchar_t));
1534 (void)wcsncpy(cnew->text, piece->text + HALF_PIECE,
1535 src->multi_src.piece_size - HALF_PIECE);
1536 piece->used = HALF_PIECE;
1537 cnew->used = src->multi_src.piece_size - HALF_PIECE;
1542 CvtStringToMultiType(XrmValuePtr args, Cardinal *num_args,
1543 XrmValuePtr fromVal, XrmValuePtr toVal)
1545 static XawAsciiType type = XawAsciiString;
1549 XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
1550 q = XrmStringToQuark(name);
1553 type = XawAsciiString;
1555 type = XawAsciiFile;
1559 XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType);
1562 toVal->size = sizeof(XawAsciiType);
1563 toVal->addr = (XPointer)&type;
1568 CvtMultiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
1569 XrmValuePtr fromVal, XrmValuePtr toVal,
1572 static String buffer;
1575 switch (*(XawAsciiType *)fromVal->addr) {
1579 case XawAsciiString:
1583 XawTypeToStringWarning(dpy, XtRAsciiType);
1589 size = strlen(buffer) + 1;
1590 if (toVal->addr != NULL) {
1591 if (toVal->size < size) {
1595 strcpy((char *)toVal->addr, buffer);
1598 toVal->addr = (XPointer)buffer;
1599 toVal->size = sizeof(String);
1606 GetDefaultPieceSize(Widget w, int offset, XrmValue *value)
1608 static XPointer pagesize;
1610 if (pagesize == 0) {
1611 pagesize = (XPointer)((long)_XawGetPageSize());
1612 if (pagesize < (XPointer)BUFSIZ)
1613 pagesize = (XPointer)BUFSIZ;
1616 value->addr = (XPointer)&pagesize;