Bug Summary

File:MultiSrc.c
Location:line 425, column 19
Description:Access to field 'next' results in a dereference of a null pointer (loaded from variable 'temp_piece')

Annotated Source Code

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