1 /*
2 * Copyright 1991 by OMRON Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name OMRON not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. OMRON makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
13 *
14 * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Authors: Chris Peterson MIT X Consortium
23 * Li Yuhong OMRON Corporation
24 * Frank Sheeran OMRON Corporation
25 *
26 * Much code taken from X11R3 String and Disk Sources.
27 */
28
29 /*
30
31 Copyright (c) 1991, 1994 X Consortium
32
33 Permission is hereby granted, free of charge, to any person obtaining a copy
34 of this software and associated documentation files (the "Software"), to deal
35 in the Software without restriction, including without limitation the rights
36 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37 copies of the Software, and to permit persons to whom the Software is
38 furnished to do so, subject to the following conditions:
39
40 The above copyright notice and this permission notice shall be included in
41 all copies or substantial portions of the Software.
42
43 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
47 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
48 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49
50 Except as contained in this notice, the name of the X Consortium shall not be
51 used in advertising or otherwise to promote the sale, use or other dealings
52 in this Software without prior written authorization from the X Consortium.
53
54 */
55
56 /*
57 * MultiSrc.c - MultiSrc object. (For use with the text widget).
58 *
59 */
60
61 #ifdef HAVE_CONFIG_H
62 #include "config.h"
63 #endif
64 #include <X11/Xaw3dxft/Xaw3dP.h>
65 #include <X11/IntrinsicP.h>
66 #include <X11/StringDefs.h>
67 #include <X11/Xfuncs.h>
68 #include <X11/Xaw3dxft/XawInit.h>
69 #include <X11/Xaw3dxft/MultiSrcP.h>
70 #include <X11/Xaw3dxft/XawImP.h>
71 #include <X11/Xmu/Misc.h>
72 #include <X11/Xmu/CharSet.h>
73 #include "XawI18n.h"
74 #include <X11/Xos.h>
75 #include <stdio.h>
76 #include <ctype.h>
77 #include <errno.h>
78
79 /****************************************************************
80 *
81 * Full class record constant
82 *
83 ****************************************************************/
84
85 /* Private Data */
86
87 static int magic_value = MAGIC_VALUE;
88
89 #define offset(field) XtOffsetOf(MultiSrcRec, multi_src.field)
90
91 static XtResource resources[] = {
92 {XtNstring, XtCString, XtRString, sizeof (XtPointer),
93 offset(string), XtRPointer, NULL},
94 {XtNtype, XtCType, XtRMultiType, sizeof (XawAsciiType),
95 offset(type), XtRImmediate, (XtPointer)XawAsciiString},
96 /* not used. */
97 {XtNdataCompression, XtCDataCompression, XtRBoolean, sizeof (Boolean),
98 offset(data_compression), XtRImmediate, (XtPointer) FALSE},
99 {XtNpieceSize, XtCPieceSize, XtRInt, sizeof (XawTextPosition),
100 offset(piece_size), XtRImmediate, (XtPointer) BUFSIZ},
101 {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
102 offset(callback), XtRCallback, (XtPointer)NULL},
103 {XtNuseStringInPlace, XtCUseStringInPlace, XtRBoolean, sizeof (Boolean),
104 offset(use_string_in_place), XtRImmediate, (XtPointer) FALSE},
105 {XtNlength, XtCLength, XtRInt, sizeof (int),
106 offset(multi_length), XtRInt, (XtPointer) &magic_value},
107
108 };
109 #undef offset
110
111 static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType,
112 XawTextScanDirection, int, Boolean);
113 static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection,
114 XawTextBlock *);
115 static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock *, int);
116 static int ReplaceText(Widget, XawTextPosition, XawTextPosition, XawTextBlock *);
117 static MultiPiece * FindPiece(MultiSrcObject, XawTextPosition, XawTextPosition *);
118 static MultiPiece * AllocNewPiece(MultiSrcObject, MultiPiece *);
119 static FILE * InitStringOrFile(MultiSrcObject, Boolean);
120 static void FreeAllPieces(MultiSrcObject);
121 static void RemovePiece(MultiSrcObject, MultiPiece *);
122 static void BreakPiece(MultiSrcObject, MultiPiece *);
123 static void LoadPieces(MultiSrcObject, FILE *, char *);
124 static void RemoveOldStringOrFile(MultiSrcObject, Boolean);
125 static void CvtStringToMultiType(XrmValuePtr, Cardinal *, XrmValuePtr, XrmValuePtr);
126 static void ClassInitialize(void);
127 static void Initialize(Widget, Widget, ArgList, Cardinal *);
128 static void Destroy(Widget);
129 static void GetValuesHook(Widget, ArgList, Cardinal *);
130 static String StorePiecesInString(MultiSrcObject);
131 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
132 static Boolean WriteToFile(String, String);
133
134 #define MyWStrncpy( t,s,wcnt ) (void) memmove( (t), (s), (wcnt)*sizeof(wchar_t))
135
136 #ifndef MyWStrncpy
137 static void (MyWStrncpy)();
138 #endif
139
140 extern char *tmpnam(String);
141 #ifdef X_NOT_STDC_ENV
142 extern int errno;
143 #endif
144
145 #ifdef X_NOT_POSIX
146 #define Off_t long
147 #define Size_t unsigned int
148 #else
149 #define Off_t off_t
150 #define Size_t size_t
151 #endif
152
153 extern wchar_t* _XawTextMBToWC(Display *, char *, int *);
154 extern char *_XawTextWCToMB(Display *, wchar_t *, int *);
155
156 #define superclass (&textSrcClassRec)
157 MultiSrcClassRec multiSrcClassRec = {
158 { /* object_class fields */
159 /* superclass */ (WidgetClass) superclass,
160 /* class_name */ "MultiSrc",
161 /* widget_size */ sizeof(MultiSrcRec),
162 /* class_initialize */ ClassInitialize,
163 /* class_part_initialize */ NULL,
164 /* class_inited */ FALSE,
165 /* initialize */ Initialize,
166 /* initialize_hook */ NULL,
167 /* pad */ NULL,
168 /* pad */ NULL,
169 /* pad */ 0,
170 /* resources */ resources,
171 /* num_resources */ XtNumber(resources),
172 /* xrm_class */ NULLQUARK,
173 /* pad */ FALSE,
174 /* pad */ FALSE,
175 /* pad */ FALSE,
176 /* pad */ FALSE,
177 /* destroy */ Destroy,
178 /* pad */ NULL,
179 /* pad */ NULL,
180 /* set_values */ SetValues,
181 /* set_values_hook */ NULL,
182 /* pad */ NULL,
183 /* get_values_hook */ GetValuesHook,
184 /* pad */ NULL,
185 /* version */ XtVersion,
186 /* callback_private */ NULL,
187 /* pad */ NULL,
188 /* pad */ NULL,
189 /* pad */ NULL,
190 /* extension */ NULL
191 },
192 { /* textSrc_class fields */
193 /* Read */ ReadText,
194 /* Replace */ ReplaceText,
195 /* Scan */ Scan,
196 /* Search */ Search,
197 /* SetSelection */ XtInheritSetSelection,
198 /* ConvertSelection */ XtInheritConvertSelection
199 },
200 { /* multiSrc_class fields */
201 /* Keep the compiler happy */ '\0'
202 }
203 };
204
205 WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec;
206
207 /************************************************************
208 *
209 * Semi-Public Interfaces.
210 *
211 ************************************************************/
212
213 /* Function Name: ClassInitialize
214 * Description: Class Initialize routine, called only once.
215 * Arguments: none.
216 * Returns: none.
217 */
218
219 static void
ClassInitialize(void)220 ClassInitialize(void)
221 {
222 XawInitializeWidgetSet();
223 XtAddConverter( XtRString, XtRMultiType, CvtStringToMultiType,
224 NULL, (Cardinal) 0);
225 }
226
227 /* Function Name: Initialize
228 * Description: Initializes the simple menu widget
229 * Arguments: request - the widget requested by the argument list.
230 * new - the new widget with both resource and non
231 * resource values.
232 * Returns: none.
233 */
234
235 /* ARGSUSED */
236 static void
Initialize(Widget request,Widget new,ArgList args,Cardinal * num_args)237 Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
238 {
239 MultiSrcObject src = (MultiSrcObject) new;
240 FILE * file;
241
242 /*
243 * Set correct flags (override resources) depending upon widget class.
244 */
245
246 src->multi_src.changes = FALSE;
247 src->multi_src.allocated_string = FALSE;
248
249 file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile);
250 LoadPieces(src, file, NULL);
251
252 if (file != NULL) fclose(file);
253 src->text_src.text_format = XawFmtWide;
254
255 }
256
257 /* Function Name: ReadText
258 * Description: This function reads the source.
259 * Arguments: w - the MultiSource widget.
260 * pos - position of the text to retreive.
261 * RETURNED text - text block that will contain returned text.
262 * length - maximum number of characters to read.
263 * Returns: The number of characters read into the buffer.
264 */
265
266 static XawTextPosition
ReadText(Widget w,XawTextPosition pos,XawTextBlock * text,int length)267 ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length)
268 {
269 MultiSrcObject src = (MultiSrcObject) w;
270 XawTextPosition count, start = 0;
271 MultiPiece * piece = FindPiece(src, pos, &start);
272
273 text->format = XawFmtWide;
274 text->firstPos = pos;
275 text->ptr = (char *)(piece->text + (pos - start));
276 count = piece->used - (pos - start);
277 text->length = (length > count) ? count : length;
278 return(pos + text->length);
279 }
280
281 /* Function Name: ReplaceText.
282 * Description: Replaces a block of text with new text.
283 * Arguments: w - the MultiSource widget.
284 * startPos, endPos - ends of text that will be removed.
285 * text - new text to be inserted into buffer at startPos.
286 * Returns: XawEditError or XawEditDone.
287 */
288
289 /*ARGSUSED*/
290 static int
ReplaceText(Widget w,XawTextPosition startPos,XawTextPosition endPos,XawTextBlock * u_text_p)291 ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos, XawTextBlock *u_text_p)
292 {
293 MultiSrcObject src = (MultiSrcObject) w;
294 MultiPiece *start_piece, *end_piece, *temp_piece;
295 XawTextPosition start_first = 0, end_first;
296 int length, firstPos;
297 wchar_t *wptr;
298 Boolean local_artificial_block = False;
299 XawTextBlock text;
300
301 /* STEP 1: The user handed me a text block called `u_text' that may be
302 * in either FMTWIDE or FMT8BIT (ie MB.) Later code needs the block
303 * `text' to hold FMTWIDE. So, this copies `u_text' to `text', and if
304 * `u_text' was MB, I knock it up to WIDE. */
305
306 if ( u_text_p->length == 0 ) /* if so, the block contents never ref'd. */
307 text.length = 0;
308
309 else if ( u_text_p->format == XawFmtWide) {
310 local_artificial_block = False; /* ie, don't have to free it ourselves*/
311 text.firstPos = u_text_p->firstPos;
312 text.length = u_text_p->length;
313 text.ptr = u_text_p->ptr;
314 /* text.format is unneeded */
315
316 } else {
317 /* WARNING! u_text->firstPos and length are in units of CHAR, not CHARACTERS! */
318
319 local_artificial_block = True; /* ie, have to free it ourselves */
320 text.firstPos = 0;
321 text.length = u_text_p->length; /* _XawTextMBToWC converts this to wchar len. */
322
323 text.ptr = (char*)_XawTextMBToWC( XtDisplay(XtParent(w)),
324 &(u_text_p->ptr[u_text_p->firstPos]), &(text.length) );
325
326 /* I assert the following assignment is not needed - since Step 4
327 depends on length, it has no need of a terminating NULL. I think
328 the ASCII-version has the same needless NULL. */
329 /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/
330 }
331
332
333 /* STEP 2: some initialization... */
334
335 if (src->text_src.edit_mode == XawtextRead)
336 return(XawEditError);
337
338 start_piece = FindPiece(src, startPos, &start_first);
339 end_piece = FindPiece(src, endPos, &end_first);
340
341
342 /* STEP 3: remove the empty pieces... */
343
344 if (start_piece != end_piece) {
345 temp_piece = start_piece->next;
346
347 /* If empty and not the only piece then remove it. */
348
349 if ( ((start_piece->used = startPos - start_first) == 0) &&
350 !((start_piece->next == NULL) && (start_piece->prev == NULL)) )
351 RemovePiece(src, start_piece);
352
353 while (temp_piece != end_piece) {
354 temp_piece = temp_piece->next;
355 RemovePiece(src, temp_piece->prev);
356 }
357 end_piece->used -= endPos - end_first;
358 if (end_piece->used != 0)
359 MyWStrncpy(end_piece->text, (end_piece->text + endPos - end_first),
360 (int) end_piece->used);
361 }
362 else { /* We are fully in one piece. */
363 if ( (start_piece->used -= endPos - startPos) == 0) {
364 if ( !((start_piece->next == NULL) && (start_piece->prev == NULL)) )
365 RemovePiece(src, start_piece);
366 }
367 else {
368 MyWStrncpy(start_piece->text + (startPos - start_first),
369 start_piece->text + (endPos - start_first),
370 (int) (start_piece->used - (startPos - start_first)) );
371 if ( src->multi_src.use_string_in_place &&
372 ((src->multi_src.length - (endPos - startPos)) <
373 (src->multi_src.piece_size - 1)) )
374 start_piece->text[src->multi_src.length - (endPos - startPos)] = (wchar_t)0;
375 }
376 }
377
378 src->multi_src.length += text.length -(endPos - startPos);
379 /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
380
381
382
383 /* STEP 4: insert the new stuff */
384
385 if ( text.length != 0) {
386
387 start_piece = FindPiece(src, startPos, &start_first);
388
389 length = text.length;
390 firstPos = text.firstPos;
391
392 while (length > 0) {
393 wchar_t* ptr;
394 int fill;
395
396 if (src->multi_src.use_string_in_place) {
397 if (start_piece->used == (src->multi_src.piece_size - 1)) {
398 /*
399 * The string is used in place, then the string
400 * is not allowed to grow.
401 */
402 start_piece->used = src->multi_src.length =
403 src->multi_src.piece_size - 1;
404 /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
405
406
407 start_piece->text[src->multi_src.length] = (wchar_t)0;
408 return(XawEditError);
409 }
410 }
411
412
413 if (start_piece->used == src->multi_src.piece_size) {
414 BreakPiece(src, start_piece);
415 start_piece = FindPiece(src, startPos, &start_first);
416 }
417
418 fill = Min((int)(src->multi_src.piece_size - start_piece->used), length);
419
420 ptr = start_piece->text + (startPos - start_first);
421 MyWStrncpy(ptr + fill, ptr,
422 (int) start_piece->used - (startPos - start_first));
423 wptr =(wchar_t *)text.ptr;
424 (void)wcsncpy(ptr, wptr + firstPos, fill);
425
426 startPos += fill;
427 firstPos += fill;
428 start_piece->used += fill;
429 length -= fill;
430 }
431 }
432
433 if ( local_artificial_block == True )
434
435 /* In other words, text is not the u_text that the user handed me but
436 one I made myself. I only care, because I need to free the string. */
437
438 XFree( text.ptr );
439
440 if (src->multi_src.use_string_in_place)
441 start_piece->text[start_piece->used] = (wchar_t)0;
442
443 src->multi_src.changes = TRUE;
444
445 XtCallCallbacks(w, XtNcallback, NULL);
446
447 return(XawEditDone);
448 }
449
450 /* Function Name: Scan
451 * Description: Scans the text source for the number and type
452 * of item specified.
453 * Arguments: w - the MultiSource widget.
454 * position - the position to start scanning.
455 * type - type of thing to scan for.
456 * dir - direction to scan.
457 * count - which occurance if this thing to search for.
458 * include - whether or not to include the character found in
459 * the position that is returned.
460 * Returns: the position of the item found.
461 *
462 * Note: While there are only 'n' characters in the file there are n+1
463 * possible cursor positions (one before the first character and
464 * one after the last character.
465 */
466
467 static
468 XawTextPosition
Scan(Widget w,XawTextPosition position,XawTextScanType type,XawTextScanDirection dir,int count,Boolean include)469 Scan(Widget w, XawTextPosition position, XawTextScanType type,
470 XawTextScanDirection dir, int count, Boolean include)
471 {
472 MultiSrcObject src = (MultiSrcObject) w;
473 int inc;
474 MultiPiece * piece;
475 XawTextPosition first = 0, first_eol_position = 0;
476 wchar_t * ptr;
477
478 if (type == XawstAll) { /* Optimize this common case. */
479 if (dir == XawsdRight)
480 return(src->multi_src.length);
481 return(0); /* else. */
482 }
483
484
485 /* STEP 1: basic sanity checks */
486
487 if (position > src->multi_src.length)
488 position = src->multi_src.length;
489
490
491 if ( dir == XawsdRight ) {
492 if (position == src->multi_src.length)
493 return(src->multi_src.length);
494 inc = 1;
495 }
496 else {
497 if (position == 0)
498 return(0);
499 inc = -1;
500 position--;
501 }
502
503 piece = FindPiece(src, position, &first);
504
505 if ( piece->used == 0 ) return(0); /* i.e., buffer is empty. */
506
507 ptr = (position - first) + piece->text;
508
509 switch (type) {
510 case XawstEOL:
511 case XawstParagraph:
512 case XawstWhiteSpace:
513 for ( ; count > 0 ; count-- ) {
514 Boolean non_space = FALSE, first_eol = TRUE;
515 /* CONSTCOND */
516 while (TRUE) {
517 wchar_t c = *ptr;
518
519 ptr += inc;
520 position += inc;
521
522 if (type == XawstWhiteSpace) {
523 if (iswspace(c)) {
524 if (non_space)
525 break;
526 }
527 else
528 non_space = TRUE;
529 }
530 else if (type == XawstEOL) {
531 if (c == _Xaw_atowc(XawLF)) break;
532 }
533 else { /* XawstParagraph */
534 if (first_eol) {
535 if (c == _Xaw_atowc(XawLF)) {
536 first_eol_position = position;
537 first_eol = FALSE;
538 }
539 }
540 else
541 if ( c == _Xaw_atowc(XawLF))
542 break;
543 else if ( !iswspace(c) )
544 first_eol = TRUE;
545 }
546
547
548 if ( ptr < piece->text ) {
549 piece = piece->prev;
550 if (piece == NULL) /* Begining of text. */
551 return(0);
552 ptr = piece->text + piece->used - 1;
553 }
554 else if ( ptr >= (piece->text + piece->used) ) {
555 piece = piece->next;
556 if (piece == NULL) /* End of text. */
557 return(src->multi_src.length);
558 ptr = piece->text;
559 }
560 }
561 }
562 if (!include) {
563 if ( type == XawstParagraph)
564 position = first_eol_position;
565 position -= inc;
566 }
567 break;
568 case XawstPositions:
569 position += count * inc;
570 break;
571 case XawstAll: /* handled in special code above */
572 default:
573 break;
574 }
575
576 if ( dir == XawsdLeft )
577 position++;
578
579 if (position >= src->multi_src.length)
580 return(src->multi_src.length);
581 if (position < 0)
582 return(0);
583
584 return(position);
585 }
586
587 /* Function Name: Search
588 * Description: Searchs the text source for the text block passed
589 * Arguments: w - the MultiSource Widget.
590 * position - the position to start scanning.
591 * dir - direction to scan.
592 * text - the text block to search for.
593 * Returns: the position of the item found.
594 */
595
596 static XawTextPosition
Search(Widget w,XawTextPosition position,XawTextScanDirection dir,XawTextBlock * text)597 Search(Widget w, XawTextPosition position, XawTextScanDirection dir, XawTextBlock *text)
598 {
599 MultiSrcObject src = (MultiSrcObject) w;
600 int inc, count = 0;
601 wchar_t * ptr;
602 wchar_t* wtarget;
603 int wtarget_len;
604 Display * d = XtDisplay(XtParent(w));
605 MultiPiece * piece;
606 wchar_t* buf;
607 XawTextPosition first = 0;
608
609 /* STEP 1: First, a brief sanity check. */
610
611 if ( dir == XawsdRight )
612 inc = 1;
613 else {
614 inc = -1;
615 if (position == 0)
616 return(XawTextSearchError); /* scanning left from 0??? */
617 position--;
618 }
619
620
621 /* STEP 2: Ensure I have a local wide string.. */
622
623 /* Since this widget stores 32bit chars, I check here to see if
624 I'm being passed a string claiming to be 8bit chars (ie, MB text.)
625 If that is the case, naturally I convert to 32bit format. */
626
627 /*if the block was FMT8BIT, length will convert to REAL wchar count below */
628 wtarget_len = text->length;
629
630 if ( text->format == XawFmtWide )
631 wtarget = &( ((wchar_t*)text->ptr) [text->firstPos] );
632 else
633 {
634 /* The following converts wtarget_len from byte len to wchar count */
635 wtarget = _XawTextMBToWC( d, &text->ptr[ text->firstPos ], &wtarget_len );
636 }
637
638 /* OK, I can now assert that wtarget holds wide characters, wtarget_len
639 holds an accurate count of those characters, and that firstPos has been
640 effectively factored out of the following computations. */
641
642
643 /* STEP 3: SEARCH! */
644
645 buf = (wchar_t *)XtMalloc((unsigned)sizeof(wchar_t) * wtarget_len );
646 (void)wcsncpy(buf, wtarget, wtarget_len );
647 piece = FindPiece(src, position, &first);
648 ptr = (position - first) + piece->text;
649
650 /* CONSTCOND */
651 while (TRUE) {
652 if (*ptr == ((dir == XawsdRight) ? *(buf + count)
653 : *(buf + wtarget_len - count - 1)) ) {
654 if (count == (text->length - 1))
655 break;
656 else
657 count++;
658 }
659 else {
660 if (count != 0) {
661 position -=inc * count;
662 ptr -= inc * count;
663 }
664 count = 0;
665 }
666
667 ptr += inc;
668 position += inc;
669
670 while ( ptr < piece->text ) {
671 piece = piece->prev;
672 if (piece == NULL) { /* Begining of text. */
673 XtFree((char *)buf);
674 return(XawTextSearchError);
675 }
676 ptr = piece->text + piece->used - 1;
677 }
678
679 while ( ptr >= (piece->text + piece->used) ) {
680 piece = piece->next;
681 if (piece == NULL) { /* End of text. */
682 XtFree((char *)buf);
683 return(XawTextSearchError);
684 }
685 ptr = piece->text;
686 }
687 }
688
689 XtFree( (char *) buf );
690 if (dir == XawsdLeft)
691 return( position );
692 return( position - ( wtarget_len - 1 ) );
693 }
694
695 /* Function Name: SetValues
696 * Description: Sets the values for the MultiSource.
697 * Arguments: current - current state of the widget.
698 * request - what was requested.
699 * new - what the widget will become.
700 * Returns: True if redisplay is needed.
701 */
702
703 /* ARGSUSED */
704 static Boolean
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * num_args)705 SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *num_args)
706 {
707 MultiSrcObject src = (MultiSrcObject) new;
708 MultiSrcObject old_src = (MultiSrcObject) current;
709 XtAppContext app_con = XtWidgetToApplicationContext(new);
710 Boolean total_reset = FALSE, string_set = FALSE;
711 FILE * file;
712 int i;
713
714 if ( old_src->multi_src.use_string_in_place !=
715 src->multi_src.use_string_in_place ) {
716 XtAppWarning( app_con,
717 "MultiSrc: The XtNuseStringInPlace resources may not be changed.");
718 src->multi_src.use_string_in_place =
719 old_src->multi_src.use_string_in_place;
720 }
721
722 for (i = 0; i < *num_args ; i++ )
723 if (streq(args[i].name, XtNstring)) {
724 string_set = TRUE;
725 break;
726 }
727
728 if ( string_set || (old_src->multi_src.type != src->multi_src.type) ) {
729 RemoveOldStringOrFile(old_src, string_set);
730 src->multi_src.allocated_string = old_src->multi_src.allocated_string;
731 file = InitStringOrFile(src, string_set);
732
733 /* Load pieces does this logic for us, but it shouldn't. Its messy.*/
734 /*if (old_src->multi_src.type == XawAsciiString)
735 LoadPieces(src, NULL, src->multi_src.string);
736 else*/
737 LoadPieces(src, file, NULL);
738 if (file != NULL) fclose(file);
739 XawTextSetSource( XtParent(new), new, 0); /* Tell text widget
740 what happened. */
741 total_reset = TRUE;
742 }
743
744 if ( old_src->multi_src.multi_length != src->multi_src.multi_length )
745 src->multi_src.piece_size = src->multi_src.multi_length;
746
747 if ( !total_reset && (old_src->multi_src.piece_size
748 != src->multi_src.piece_size) ) {
749 String mb_string = StorePiecesInString( old_src );
750
751 if ( mb_string != 0 ) {
752 FreeAllPieces( old_src );
753 LoadPieces( src, NULL, mb_string );
754 XtFree( mb_string );
755 } else {
756 /* If the buffer holds bad chars, don't touch it... */
757 XtAppWarningMsg( app_con,
758 "convertError", "multiSource", "XawError",
759 XtName( XtParent( (Widget) old_src ) ), NULL, NULL );
760 XtAppWarningMsg( app_con,
761 "convertError", "multiSource", "XawError",
762 "Non-character code(s) in buffer.", NULL, NULL );
763 }
764 }
765
766 return(FALSE);
767 }
768
769 /* Function Name: GetValuesHook
770 * Description: This is a get values hook routine that sets the
771 * values specific to the multi source.
772 * Arguments: w - the MultiSource Widget.
773 * args - the argument list.
774 * num_args - the number of args.
775 * Returns: none.
776 */
777
778 static void
GetValuesHook(Widget w,ArgList args,Cardinal * num_args)779 GetValuesHook(Widget w, ArgList args, Cardinal *num_args)
780 {
781 MultiSrcObject src = (MultiSrcObject) w;
782 int i;
783
784 if (src->multi_src.type == XawAsciiString) {
785 for (i = 0; i < *num_args ; i++ )
786 if (streq(args[i].name, XtNstring)) {
787 if (src->multi_src.use_string_in_place) {
788 *((char **) args[i].value) = (char *)
789 src->multi_src.first_piece->text;
790 }
791 else {
792 if (_XawMultiSave(w)) /* If save sucessful. */
793 *((char **) args[i].value) = src->multi_src.string;
794 }
795 break;
796 }
797 }
798 }
799
800 /* Function Name: Destroy
801 * Description: Destroys an multi source (frees all data)
802 * Arguments: src - the Multi source Widget to free.
803 * Returns: none.
804 */
805
806 static void
Destroy(Widget w)807 Destroy(Widget w)
808 {
809 RemoveOldStringOrFile((MultiSrcObject) w, True);
810 }
811
812 /************************************************************
813 *
814 * Public routines
815 *
816 ************************************************************/
817
818 /* Function Name: XawMultiSourceFreeString
819 * Description: Frees the string returned by a get values call
820 * on the string when the source is of type string.
821 * Arguments: w - the MultiSrc widget.
822 * Returns: none.
823 *
824 * The public interface is XawAsciiSourceFreeString!
825 */
826
827 void
_XawMultiSourceFreeString(Widget w)828 _XawMultiSourceFreeString(
829 Widget w)
830 {
831 MultiSrcObject src = (MultiSrcObject) w;
832
833 /*if (src->multi_src.allocated_string&& src->multi_src.type != XawAsciiFile) {*/
834 /* ASSERT: src->multi_src.allocated_string -> we MUST free .string! */
835 if ( src->multi_src.allocated_string ) {
836 XtFree(src->multi_src.string);
837 src->multi_src.allocated_string = FALSE;
838 src->multi_src.string = NULL;
839 }
840 }
841
842 /* Function Name: _XawMultiSave
843 * Description: Saves all the pieces into a file or string as required.
844 * Arguments: w - the multiSrc Widget.
845 * Returns: TRUE if the save was successful.
846 *
847 * The public interface is XawAsciiSave(w)!
848 */
849
850 Boolean
_XawMultiSave(Widget w)851 _XawMultiSave(
852 Widget w)
853 {
854 MultiSrcObject src = (MultiSrcObject) w;
855 XtAppContext app_con = XtWidgetToApplicationContext(w);
856 char * mb_string;
857
858 /*
859 * If using the string in place then there is no need to play games
860 * to get the internal info into a readable string.
861 */
862
863 if (src->multi_src.use_string_in_place)
864 return(TRUE);
865
866 if (src->multi_src.type == XawAsciiFile) {
867
868 if (!src->multi_src.changes) /* No changes to save. */
869 return(TRUE);
870
871 mb_string = StorePiecesInString( src );
872
873 if ( mb_string != 0 ) {
874 if ( WriteToFile( mb_string, src->multi_src.string ) == FALSE ) {
875 XtFree( mb_string );
876 return( FALSE );
877 }
878 XtFree( mb_string );
879 src->multi_src.changes = FALSE;
880 return( TRUE );
881 } else {
882 /* If the buffer holds bad chars, don't touch it... */
883 XtAppWarningMsg( app_con,
884 "convertError", "multiSource", "XawError",
885 "Due to illegal characters, file not saved.", NULL, NULL);
886 return( FALSE );
887 }
888 }
889 else {
890
891 /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED? The manual
892 says this routine's only function is to save files to disk. -Sheeran */
893
894 mb_string = StorePiecesInString( src );
895
896 if ( mb_string == 0 ) {
897 /* If the buffer holds bad chars, don't touch it... */
898 XtAppWarningMsg( app_con,
899 "convertError", "multiSource", "XawError",
900 XtName( XtParent( (Widget) src ) ), NULL, NULL);
901 return( FALSE );
902 }
903
904 /* assert: mb_string holds good characters so the buffer is fine */
905 if (src->multi_src.allocated_string == TRUE)
906 XtFree(src->multi_src.string);
907 else
908 src->multi_src.allocated_string = TRUE;
909
910 src->multi_src.string = mb_string;
911 }
912 src->multi_src.changes = FALSE;
913 return(TRUE);
914 }
915
916 /* Function Name: XawMultiSaveAsFile
917 * Description: Save the current buffer as a file.
918 * Arguments: w - the MultiSrc widget.
919 * name - name of the file to save this file into.
920 * Returns: True if the save was sucessful.
921 *
922 * The public interface is XawAsciiSaveAsFile!
923 */
924
925 Boolean
_XawMultiSaveAsFile(Widget w,_Xconst char * name)926 _XawMultiSaveAsFile(
927 Widget w,
928 _Xconst char* name)
929 {
930 MultiSrcObject src = (MultiSrcObject) w;
931 String mb_string;
932 Boolean ret;
933
934 mb_string = StorePiecesInString( src );
935
936 if ( mb_string != 0 ) {
937 ret = WriteToFile( mb_string, (char *)name );
938 XtFree( mb_string );
939 return( ret );
940 }
941
942 /* otherwise there was a conversion error. So print widget name too. */
943 XtAppWarningMsg( XtWidgetToApplicationContext(w),
944 "convertError", "multiSource", "XawError",
945 XtName( XtParent( (Widget) src ) ), NULL, NULL);
946 return( False );
947 }
948
949 /************************************************************
950 *
951 * Private Functions.
952 *
953 ************************************************************/
954
955 static void
RemoveOldStringOrFile(MultiSrcObject src,Boolean checkString)956 RemoveOldStringOrFile(MultiSrcObject src, Boolean checkString)
957 {
958 FreeAllPieces(src);
959
960 if (checkString && src->multi_src.allocated_string) {
961 XtFree(src->multi_src.string);
962 src->multi_src.allocated_string = False;
963 src->multi_src.string = NULL;
964 }
965 }
966
967 /* Function Name: WriteToFile
968 * Description: Write the string specified to the begining of the file
969 * specified.
970 * Arguments: string - string to write.
971 * name - the name of the file
972 * Returns: returns TRUE if sucessful, FALSE otherwise.
973 */
974
975 static Boolean
WriteToFile(String string,String name)976 WriteToFile(String string, String name)
977 {
978 int fd;
979
980 if ( ((fd = creat(name, 0666)) == -1 ) ||
981 (write(fd, string, sizeof(unsigned char) * strlen(string)) == -1) )
982 return(FALSE);
983
984 if ( close(fd) == -1 )
985 return(FALSE);
986
987 return(TRUE);
988 }
989
990
991 /* Function Name: StorePiecesInString
992 * Description: store the pieces in memory into a char string.
993 * Arguments: src - the multiSrc to gather data from
994 * Returns: char *mb_string. Caller must free.
995 * or 0: conversion error. Caller must panic!
996 */
997
998 static String
StorePiecesInString(MultiSrcObject src)999 StorePiecesInString(MultiSrcObject src)
1000 {
1001 wchar_t* wc_string;
1002 char *mb_string;
1003 int char_count = src->multi_src.length;
1004 XawTextPosition first;
1005 MultiPiece * piece;
1006
1007 /* I believe the char_count + 1 and the NULL termination are unneeded! FS*/
1008
1009 wc_string = (wchar_t*) XtMalloc((unsigned)(char_count + 1) * sizeof(wchar_t));
1010
1011 for (first = 0, piece = src->multi_src.first_piece ; piece != NULL;
1012 first += piece->used, piece = piece->next)
1013 (void) wcsncpy( wc_string + first, piece->text, piece->used );
1014
1015 wc_string[ char_count ] = (wchar_t)0; /* NULL terminate this sucker. */
1016
1017
1018 /* This will refill all pieces to capacity. */
1019
1020 if ( src->multi_src.data_compression ) {
1021 FreeAllPieces( src );
1022 LoadPieces( src, NULL, (char *)wc_string );
1023 }
1024
1025 /* Lastly, convert it to a MB format and send it back. */
1026
1027 mb_string = _XawTextWCToMB( XtDisplayOfObject( (Widget)src ),
1028 wc_string, &char_count );
1029
1030 /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED. */
1031 XtFree( (char*) wc_string );
1032 return( mb_string );
1033 }
1034
1035
1036 /* Function Name: InitStringOrFile.
1037 * Description: Initializes the string or file.
1038 * Arguments: src - the MultiSource.
1039 * Returns: none - May exit though.
1040 */
1041
1042 static FILE *
InitStringOrFile(MultiSrcObject src,Boolean newString)1043 InitStringOrFile(MultiSrcObject src, Boolean newString)
1044 {
1045 char * open_mode = NULL;
1046 FILE * file;
1047 char fileName[TMPSIZ];
1048 Display *d = XtDisplayOfObject((Widget)src);
1049
1050 if (src->multi_src.type == XawAsciiString) {
1051
1052 if (src->multi_src.string == NULL)
1053 src->multi_src.length = 0;
1054
1055 else if (! src->multi_src.use_string_in_place) {
1056 int length;
1057 String temp = XtNewString(src->multi_src.string);
1058 if ( src->multi_src.allocated_string )
1059 XtFree( src->multi_src.string );
1060 src->multi_src.allocated_string = True;
1061 src->multi_src.string = temp;
1062
1063 length = strlen(src->multi_src.string);
1064
1065 /* Wasteful, throwing away the WC string, but need side effect! */
1066 (void) _XawTextMBToWC(d, src->multi_src.string, &length);
1067 src->multi_src.length = (XawTextPosition) length;
1068 } else {
1069 src->multi_src.length = strlen(src->multi_src.string);
1070 /* In case the length resource is incorrectly set */
1071 if (src->multi_src.length > src->multi_src.multi_length)
1072 src->multi_src.multi_length = src->multi_src.length;
1073
1074 if (src->multi_src.multi_length == MAGIC_VALUE)
1075 src->multi_src.piece_size = src->multi_src.length;
1076 else
1077 src->multi_src.piece_size = src->multi_src.multi_length + 1;
1078 }
1079
1080 /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
1081 return(NULL);
1082 }
1083
1084 /*
1085 * type is XawAsciiFile.
1086 */
1087
1088 src->multi_src.is_tempfile = FALSE;
1089
1090 switch (src->text_src.edit_mode) {
1091 case XawtextRead:
1092 if (src->multi_src.string == NULL)
1093 XtErrorMsg("NoFile", "multiSourceCreate", "XawError",
1094 "Creating a read only disk widget and no file specified.",
1095 NULL, 0);
1096 open_mode = "r";
1097 break;
1098 case XawtextAppend:
1099 case XawtextEdit:
1100 if (src->multi_src.string == NULL) {
1101
1102 if ( src->multi_src.allocated_string )
1103 XtFree( src->multi_src.string );
1104 src->multi_src.allocated_string = False;
1105 src->multi_src.string = fileName;
1106
1107 (void) tmpnam(src->multi_src.string);
1108 src->multi_src.is_tempfile = TRUE;
1109 open_mode = "w";
1110 } else
1111 open_mode = "r+";
1112 break;
1113 default:
1114 XtErrorMsg("badMode", "multiSourceCreate", "XawError",
1115 "Bad editMode for multi source; must be Read, Append or Edit.",
1116 NULL, NULL);
1117 }
1118
1119 /* Allocate new memory for the temp filename, because it is held in
1120 * a stack memory buffer. We must verify that all routines that set
1121 * .string first check .allocated_string and free it - plumbing Sheeran.
1122 */
1123 if (newString || src->multi_src.is_tempfile) {
1124 if ( src->multi_src.allocated_string )
1125 src->multi_src.string = XtNewString(src->multi_src.string);
1126 src->multi_src.allocated_string = TRUE;
1127 }
1128
1129 if (!src->multi_src.is_tempfile) {
1130 if ((file = fopen(src->multi_src.string, open_mode)) != 0) {
1131 (void) fseek(file, (Off_t)0, 2);
1132 src->multi_src.length = ftell (file);
1133 return file;
1134 } else {
1135 String params[2];
1136 Cardinal num_params = 2;
1137
1138 params[0] = src->multi_src.string;
1139 params[1] = strerror(errno);
1140 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
1141 "openError", "multiSourceCreate", "XawWarning",
1142 "Cannot open file %s; %s", params, &num_params);
1143 }
1144 }
1145 src->multi_src.length = 0;
1146 return((FILE *)NULL);
1147 #undef StrLen
1148 }
1149
1150 /* LoadPieces: This routine takes either the MB contents of open file `file' or the
1151 MB contents of string or the MB contents of src->multi_src.string and places
1152 them in Pieces in WC format.
1153
1154 CAUTION: You must have src->multi_src.length set to file length bytes
1155 when src->multi_src.type == XawAsciiFile. src->multi_src.length must be
1156 the length of the parameter string if string is non-NULL. */
1157
1158 static void
LoadPieces(MultiSrcObject src,FILE * file,char * string)1159 LoadPieces(MultiSrcObject src, FILE *file, char *string)
1160 {
1161 Display *d = XtDisplayOfObject((Widget)src);
1162 wchar_t* local_str, *ptr;
1163 MultiPiece* piece = NULL;
1164 XawTextPosition left;
1165 int bytes = sizeof(wchar_t);
1166 char* temp_mb_holder = NULL;
1167
1168 /*
1169 * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg
1170 * in as MB length, out as WC length. We want local_length to be
1171 * WC count.
1172 */
1173 int local_length = src->multi_src.length;
1174
1175 if (string != NULL) {
1176 /*
1177 * ASSERT: IF our caller passed a non-null string, THEN
1178 * src->multi_src.length is currently string's * byte count,
1179 * AND string is in a MB format.
1180 */
1181 local_str = _XawTextMBToWC(d, (char *)string, &local_length);
1182 src->multi_src.length = (XawTextPosition) local_length;
1183 } else if (src->multi_src.type != XawAsciiFile) {
1184 /*
1185 * here, we are not changing the contents, just reloading,
1186 * so don't change len...
1187 */
1188 local_length = src->multi_src.string ?
1189 strlen( src->multi_src.string ) : 0;
1190 local_str = _XawTextMBToWC( d, (char*)src->multi_src.string, &local_length );
1191 } else {
1192 if (src->multi_src.length != 0) {
1193 temp_mb_holder =
1194 XtMalloc((unsigned)(src->multi_src.length + 1) * sizeof(unsigned char));
1195 fseek(file, (Off_t)0, 0);
1196 src->multi_src.length = fread (temp_mb_holder,
1197 (Size_t)sizeof(unsigned char),
1198 (Size_t)src->multi_src.length, file);
1199 if (src->multi_src.length <= 0)
1200 XtAppErrorMsg( XtWidgetToApplicationContext ((Widget) src),
1201 "readError", "multiSource", "XawError",
1202 "fread returned error.", NULL, NULL);
1203 local_length = src->multi_src.length;
1204 local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length);
1205 src->multi_src.length = local_length;
1206
1207 if ( local_str == 0 ) {
1208 String params[2];
1209 Cardinal num_params;
1210 static char err_text[] =
1211 "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>";
1212
1213 params[0] = XtName(XtParent((Widget)src));
1214 params[1] = src->multi_src.string;
1215 num_params = 2;
1216
1217 XtAppWarningMsg( XtWidgetToApplicationContext((Widget)src),
1218 "readLocaleError", "multiSource", "XawError",
1219 "%s: The file `%s' contains characters not representable in this locale.",
1220 params, &num_params);
1221 src->multi_src.length = sizeof err_text;
1222 local_length = src->multi_src.length;
1223 local_str = _XawTextMBToWC(d, err_text, &local_length);
1224 src->multi_src.length = local_length;
1225 }
1226 } else { /*ASSERT that since following while loop looks at local_length
1227 this isn't needed. Sheeran, Omron KK, 1993/07/15
1228 temp_mb_holder[src->multi_src.length] = '\0';*/
1229 local_str = (wchar_t*)temp_mb_holder;
1230 }
1231 }
1232
1233 if (src->multi_src.use_string_in_place) {
1234 piece = AllocNewPiece(src, piece);
1235 piece->used = Min(src->multi_src.length, src->multi_src.piece_size);
1236 piece->text = (wchar_t*)src->multi_src.string;
1237 return;
1238 }
1239
1240 ptr = local_str;
1241 left = local_length;
1242
1243 do {
1244 piece = AllocNewPiece(src, piece);
1245
1246 piece->text = (wchar_t*)XtMalloc(src->multi_src.piece_size * bytes);
1247 piece->used = Min(left, src->multi_src.piece_size);
1248 if (piece->used != 0)
1249 (void) wcsncpy(piece->text, ptr, piece->used);
1250
1251 left -= piece->used;
1252 ptr += piece->used;
1253 } while (left > 0);
1254
1255 if ( temp_mb_holder )
1256 XtFree( (char*) temp_mb_holder );
1257 }
1258
1259
1260 /* Function Name: AllocNewPiece
1261 * Description: Allocates a new piece of memory.
1262 * Arguments: src - The MultiSrc Widget.
1263 * prev - the piece just before this one, or NULL.
1264 * Returns: the allocated piece.
1265 */
1266
1267 static MultiPiece *
AllocNewPiece(MultiSrcObject src,MultiPiece * prev)1268 AllocNewPiece(MultiSrcObject src, MultiPiece *prev)
1269 {
1270 MultiPiece * piece = XtNew(MultiPiece);
1271
1272 if (prev == NULL) {
1273 src->multi_src.first_piece = piece;
1274 piece->next = NULL;
1275 }
1276 else {
1277 if (prev->next != NULL)
1278 (prev->next)->prev = piece;
1279 piece->next = prev->next;
1280 prev->next = piece;
1281 }
1282
1283 piece->prev = prev;
1284
1285 return(piece);
1286 }
1287
1288 /* Function Name: FreeAllPieces
1289 * Description: Frees all the pieces
1290 * Arguments: src - The MultiSrc Widget.
1291 * Returns: none.
1292 */
1293
1294 static void
FreeAllPieces(MultiSrcObject src)1295 FreeAllPieces(MultiSrcObject src)
1296 {
1297 MultiPiece * next, * first = src->multi_src.first_piece;
1298
1299 if (first->prev != NULL)
1300 printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n");
1301
1302 for ( ; first != NULL ; first = next ) {
1303 next = first->next;
1304 RemovePiece(src, first);
1305 }
1306 }
1307
1308 /* Function Name: RemovePiece
1309 * Description: Removes a piece from the list.
1310 * Arguments:
1311 * piece - the piece to remove.
1312 * Returns: none.
1313 */
1314
1315 static void
RemovePiece(MultiSrcObject src,MultiPiece * piece)1316 RemovePiece(MultiSrcObject src, MultiPiece *piece)
1317 {
1318 if (piece->prev == NULL)
1319 src->multi_src.first_piece = piece->next;
1320 else
1321 (piece->prev)->next = piece->next;
1322
1323 if (piece->next != NULL)
1324 (piece->next)->prev = piece->prev;
1325
1326 if (!src->multi_src.use_string_in_place)
1327 XtFree((char *)piece->text);
1328
1329 XtFree((char *)piece);
1330 }
1331
1332 /* Function Name: FindPiece
1333 * Description: Finds the piece containing the position indicated.
1334 * Arguments: src - The MultiSrc Widget.
1335 * position - the position that we are searching for.
1336 * RETURNED first - the position of the first character in this piece.
1337 * Returns: piece - the piece that contains this position.
1338 */
1339
1340 static MultiPiece *
FindPiece(MultiSrcObject src,XawTextPosition position,XawTextPosition * first)1341 FindPiece(MultiSrcObject src, XawTextPosition position, XawTextPosition *first)
1342 {
1343 MultiPiece * old_piece = NULL, * piece = src->multi_src.first_piece;
1344 XawTextPosition temp;
1345
1346 for ( temp = 0 ; piece != NULL ; temp += piece->used, piece = piece->next ) {
1347 *first = temp;
1348 old_piece = piece;
1349
1350 if ((temp + piece->used) > position)
1351 return(piece);
1352 }
1353 return(old_piece); /* if we run off the end the return the last piece */
1354 }
1355
1356 /* Function Name: BreakPiece
1357 * Description: Breaks a full piece into two new pieces.
1358 * Arguments: src - The MultiSrc Widget.
1359 * piece - the piece to break.
1360 * Returns: none.
1361 */
1362
1363 #define HALF_PIECE (src->multi_src.piece_size/2)
1364
1365 static void
BreakPiece(MultiSrcObject src,MultiPiece * piece)1366 BreakPiece(MultiSrcObject src, MultiPiece *piece)
1367 {
1368 MultiPiece * new = AllocNewPiece(src, piece);
1369
1370 new->text = (wchar_t*)XtMalloc(src->multi_src.piece_size * sizeof(wchar_t));
1371 (void) wcsncpy(new->text, piece->text + HALF_PIECE,
1372 src->multi_src.piece_size - HALF_PIECE);
1373 piece->used = HALF_PIECE;
1374 new->used = src->multi_src.piece_size - HALF_PIECE;
1375 }
1376
1377 /* Convert string "XawAsciiString" and "XawAsciiFile" to quarks. */
1378
1379 /* ARGSUSED */
1380 static void
CvtStringToMultiType(XrmValuePtr args,Cardinal * num_args,XrmValuePtr fromVal,XrmValuePtr toVal)1381 CvtStringToMultiType(XrmValuePtr args, Cardinal *num_args, XrmValuePtr fromVal,
1382 XrmValuePtr toVal)
1383 {
1384 static XawAsciiType type;
1385 static XrmQuark XtQEstring = NULLQUARK;
1386 static XrmQuark XtQEfile;
1387 XrmQuark q;
1388 char lowerName[40];
1389
1390 if (XtQEstring == NULLQUARK) {
1391 XtQEstring = XrmPermStringToQuark(XtEstring);
1392 XtQEfile = XrmPermStringToQuark(XtEfile);
1393 }
1394
1395 if (strlen ((char*) fromVal->addr) < sizeof lowerName) {
1396 XmuCopyISOLatin1Lowered(lowerName, (char *) fromVal->addr);
1397 q = XrmStringToQuark(lowerName);
1398
1399 if (q == XtQEstring) type = XawAsciiString;
1400 else if (q == XtQEfile) type = XawAsciiFile;
1401 else {
1402 toVal->size = 0;
1403 toVal->addr = NULL;
1404 return;
1405 }
1406 toVal->size = sizeof type;
1407 toVal->addr = (XPointer) &type;
1408 return;
1409 }
1410 toVal->size = 0;
1411 toVal->addr = NULL;
1412 }
1413