1 /* $XConsortium: FormatUtil.c /main/9 1996/11/01 10:12:14 drk $ */
2 /************************************<+>*************************************
3 ****************************************************************************
7 ** Project: Text Graphic Display Library
10 ** Description: Semi private format utility functions that do not
11 ** require the Display Area, Motif, Xt or X11.
14 ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
16 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
17 ** (c) Copyright 1993, 1994 International Business Machines Corp.
18 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
19 ** (c) Copyright 1993, 1994 Novell, Inc.
22 ****************************************************************************
23 ************************************<+>*************************************/
42 * Canvas Engine includes
45 #include "CanvasSegP.h"
50 #include "CanvasError.h"
52 #include "FormatUtilI.h"
54 #if defined(NLS16) || !defined(NO_MESSAGE_CATALOG)
59 static const int NL_CAT_LOCALE = 0;
62 /******** Private Function Declarations ********/
63 /******** End Private Function Declarations ********/
65 /******************************************************************************
67 * Private variables and defines.
69 *****************************************************************************/
72 /******************************************************************************
76 *****************************************************************************/
77 /******************************************************************************
79 * Semi Public Functions
81 *****************************************************************************/
82 /******************************************************************************
83 * Function: int _DtHelpCeAddOctalToBuf (char *src, char **dst,
85 * int *dst_max, int grow_size)
88 * src Specifies a pointer to a string.
89 * dst Specifies a pointer to the buffer to
90 * to hold the information.
91 * dst_size Specifies the current size of 'dst'.
92 * Returns the new size of 'dst'.
93 * dst_max Specifies the current maximum size of 'dst'.
94 * Returns the new maximum size of 'dst'.
95 * grow_size Specifies the minimum grow size of 'dst'
96 * when a malloc/realloc occurs.
97 * If this is less than one, 'dst' will
98 * grow only large enough to hold
101 * Returns: 0 if successful, -1 if errors.
107 * Purpose: (Re-)Allocates, if necessary, enough memory to hold the old
108 * information plus the byte.
109 * Coverts the 0xXX value pointed to by src to a 0-256 by value.
110 * Appends the character to the buffer pointed to 'dst'.
111 * Updates 'dst_size' to include the new character.
112 * Updates 'dst_max' to the new size of 'dst' if a
113 * malloc/realloc occurred.
115 *****************************************************************************/
117 _DtHelpCeAddOctalToBuf(
129 dst == NULL || dst_size == NULL || dst_max == NULL ||
130 (*dst == NULL && (*dst_size || *dst_max)))
137 if ((*dst_size + 2) >= *dst_max)
139 if (grow_size > *dst_size + 3 - *dst_max)
140 *dst_max = *dst_max + grow_size;
142 *dst_max = *dst_size + 3;
145 dstPtr = (char *) realloc ((void *) dstPtr, *dst_max);
148 dstPtr = (char *) malloc (sizeof(char) * (*dst_max));
155 * check to see if we have good memory
159 errno = CEErrorMalloc;
165 value = strtoul (src, NULL, 16);
168 if ((value == ULONG_MAX && errno == ERANGE) || value > 255 || value < 1)
170 errno = CEErrorFormattingValue;
175 * copy the source into the destination
177 dstPtr[*dst_size] = (char ) value;
180 * adjust the pointers.
182 *dst_size = *dst_size + 1;
185 * null the end of the buffer.
187 dstPtr[*dst_size] = '\0';
192 /******************************************************************************
193 * Function: int __CEAppendCharToInfo (char **src, char **dst, int *dst_size,
194 * int *dst_max, int grow_size)
197 * src Specifies a pointer to a string.
198 * dst Specifies a pointer to the buffer to
199 * to hold the information.
200 * dst_size Specifies the current size of 'dst'.
201 * Returns the new size of 'dst'.
202 * dst_max Specifies the current maximum size of 'dst'.
203 * Returns the new maximum size of 'dst'.
204 * grow_size Specifies the minimum grow size of 'dst'
205 * when a malloc/realloc occurs.
206 * If this is less than one, 'dst' will
207 * grow only large enough to hold
210 * Returns: 0 if successful, -1 if errors.
216 * Purpose: (Re-)Allocates, if necessary, enough memory to hold the old
217 * information plus the new.
218 * Appends the character pointed to by 'src' to the buffer
220 * Updates 'src' to point to the next character after the
221 * one appended to 'dst'.
222 * Updates 'dst_size' to include the new character.
223 * Updates 'dst_max' to the new size of 'dst' if a
224 * malloc/realloc occurred.
226 *****************************************************************************/
228 _DtHelpCeAddCharToBuf(
238 if (src == NULL || *src == NULL ||
239 dst == NULL || dst_size == NULL || dst_max == NULL ||
240 (*dst == NULL && (*dst_size || *dst_max)))
248 if ((*dst_size + 2) >= *dst_max)
250 if (grow_size > *dst_size + 3 - *dst_max)
251 *dst_max = *dst_max + grow_size;
253 *dst_max = *dst_size + 3;
256 dstPtr = (char *) realloc ((void *) dstPtr, *dst_max);
259 dstPtr = (char *) malloc (*dst_max);
266 * check to see if we have good memory
270 errno = CEErrorMalloc;
275 * copy the source into the destination
277 dstPtr[*dst_size] = *srcPtr++;
280 * adjust the pointers.
283 *dst_size = *dst_size + 1;
286 * null the end of the buffer.
288 dstPtr[*dst_size] = '\0';
293 /******************************************************************************
294 * Function: int _DtHelpCeAddStrToBuf (char **src, char **dst, int *dst_size,
295 * int *dst_max, int copy_size, int grow_size)
298 * src Specifies a pointer to a string.
299 * dst Specifies a pointer to the buffer to
300 * to hold the information.
301 * dst_size Specifies the current size of 'dst'.
302 * Returns the new size of 'dst'.
303 * dst_max Specifies the current maximum size of 'dst'.
304 * Returns the new maximum size of 'dst'.
305 * copy_size Specifies the number of characters to
306 * copy from 'src' to 'dst'.
307 * grow_size Specifies the minimum grow size of 'dst'
308 * when a malloc/realloc occurs.
309 * If this is less than one, 'dst' will
310 * grow only large enough to hold
313 * Returns: 0 if successful, -1 if errors.
319 * Purpose: Copys 'copy_size' number of characters of 'src'
321 * Updates 'src', to point after 'copy_size' number of
323 * Updates the 'dst_size' to reflect the number of characters
325 * If required, increments dst_max and (re)allocs memory
326 * to hold the extra 'copy_size' number of characters.
328 *****************************************************************************/
330 _DtHelpCeAddStrToBuf (
344 if (src == NULL || *src == NULL || (((int)strlen(*src)) < copy_size)
345 || dst == NULL || dst_size == NULL || dst_max == NULL
346 || (*dst == NULL && (*dst_size || *dst_max)))
355 if ((*dst_size + copy_size + 1) >= *dst_max)
357 if (grow_size > (*dst_size + copy_size + 2 - *dst_max))
358 *dst_max = *dst_max + grow_size;
360 *dst_max = *dst_size + copy_size + 2;
363 dstPtr = (char *) realloc ((void *) dstPtr, *dst_max);
366 dstPtr = (char *) malloc (*dst_max);
374 errno = CEErrorMalloc;
379 * make sure there is a null byte to append to.
381 dstPtr[*dst_size] = '\0';
384 * copy the source into the destination
386 strncat (dstPtr, srcPtr, copy_size);
389 * adjust the pointers
391 *src = srcPtr + copy_size;
392 *dst_size = *dst_size + copy_size;
397 /******************************************************************************
398 * Function: int _DtHelpCeGetNxtBuf (FILE *file, char *dst, char **src,
402 * file Specifies a stream to read from.
403 * dst Specifies the buffer where new information
405 * src Specifies a pointer into 'dst'. If there
406 * is information left over, it
407 * is moved to the begining of 'dst'.
408 * Returns 'src' pointing to 'dst'.
409 * max_size Specifies the maximum size of 'dst'.
411 * Returns: 0 if this is the last buffer that can be read for the topic.
413 * >0 if more to be read.
416 * read (2) Errors set via a read call.
420 * Purpose: Reads the next buffer of information.
422 *****************************************************************************/
439 (void ) strcpy (dst, (*src));
440 leftOver = strlen (dst);
442 result = _DtHelpCeReadBuf (file, &(dst[leftOver]), (max_size - leftOver));
445 * check to see if we ran into trouble reading this buffer
446 * of information. If not reset the pointer to the beginning
456 /******************************************************************************
457 * Function: int _DtHelpCeReadBuf (FILE *file, char *buffer, int size)
459 * Parameters: FILE Specifies the stream to read from.
460 * buffer Specifies a buffer to read information
462 * size Specifies the maximum number of bytes
463 * 'buffer' can contain. It should never be
464 * larger than 'buffer' can hold, but it can
467 * Returns: 0 if this is the last buffer that can be read for the topic.
469 * >0 if more to be read.
472 * read (2) Errors set via a read call.
474 * Purpose: Get size-1 number of bytes into a buffer and possibly
475 * check for page markers imbedded within the text.
477 *****************************************************************************/
487 * take into account the last byte must be an end of string marker.
491 flag = _DtHelpCeBufFileRd(file, buffer, size);
498 } /* End _DtHelpCeReadBuf */
500 /******************************************************************************
501 * Function: char *_DtHelpGetNxtToken (char *str, char **retToken)
504 * str The string (in memory) which is being
506 * retToken Returns the next token from the input.
507 * Valid tokens are strings of non-whitespace
508 * characters, newline ("\n"), and
509 * end-of-data (indicated by a zero length
512 * A NULL value indicates an error.
514 * Newline or zero length strings are
515 * not owned by the caller.
517 * Otherwise, the memory for the returned
518 * token is owned by the caller.
520 * Return Value: Returns the pointer to the next unparsed character in
521 * the input string. A NULL value indicates an error.
527 * Purpose: Parse tokens in resource string values.
529 *****************************************************************************/
541 if (retToken) *retToken = NULL; /* tested in caller code */
543 if (str == NULL || *str == '\0' || retToken == NULL)
549 /* Find the next token in the string. The parsing rules are:
551 - Whitespace (except for \n) separates tokens.
552 - \n is a token itself.
553 - The \0 at the end of the string is a token.
556 /* Skip all of the whitespace (except for \n). */
557 while (*str && (*str != '\n') && isspace (*str))
560 /* Str is pointing at the start of the next token. Depending on the
561 type of token, malloc the memory and copy the token value. */
565 else if (*str == '\n') {
571 /* We have some non-whitespace characters. Find the end of */
572 /* them and copy them into new memory. */
573 if ((MB_CUR_MAX == 1 || mblen (str, MB_CUR_MAX) == 1) && *str == '\"')
576 * found a quoted token - skip the quote.
583 while (*str && !done)
586 * get the length of the item.
591 len = mblen (str, MB_CUR_MAX);
598 * check for the token terminator
600 if ((quote && *str == '\"') ||
601 (!quote && (isspace (*str) || *str == '\n')))
611 * determine the length of the token.
613 token = (char *) malloc ((str - start + 1) * sizeof (char));
616 strncpy (token, start, str - start);
617 *(token + (str - start)) = '\0';
620 errno = CEErrorMalloc;
623 * skip the quote terminator
625 if (quote && len == 1 && *str == '\"')
633 /******************************************************************************
634 * Function: _DtCvSegment *_DtHelpAllocateSegments(int malloc_size)
637 * malloc_size Specifies the number of segments to
638 * allocate if 'alloc_size' is NULL or less
639 * than 1 or if '*next_seg' is NULL. The
640 * first one is returned to the caller with
641 * the rest in 'next_seg' if 'next_seg' is
645 * non-null If succeeds.
648 * Purpose: Allocate a block of segments, zeros the structures, and
649 * sets the link_idx of each structure to -1.
651 *****************************************************************************/
653 _DtHelpAllocateSegments (
657 _DtCvSegment *newSeg;
661 * don't allow zero or negative allocations
667 * allocate the block of segments
669 newSeg = (_DtCvSegment *) calloc (sizeof(_DtCvSegment), malloc_size);
673 * now allocate the same number of private information structures
675 p = (FrmtPrivateInfo *) calloc (sizeof(FrmtPrivateInfo), malloc_size);
679 * mark the first item as the top block. Since it will be
680 * attached to the first segment, it marks both the segment
681 * and the private information blocks for later frees.
684 for (i = 0; i < malloc_size; i++)
687 * invalidate the link index and attach a private
688 * information structure to each segment
690 newSeg[i].link_idx = -1;
691 newSeg[i].client_use = p++;
697 * had trouble allocating the private information.
698 * free the new segment list and return NULL as an error.
708 /******************************************************************************
709 * Function: int _DtHelpFmtFindBreak (char *ptr, int mb_len, int *num_chars)
712 * ptr Specifies the string to check.
713 * mb_len Specifies if the sequence should be single
714 * byte or multi-byte.
715 * num_chars Returns the character count.
717 * Returns number of bytes in the sequence.
721 * Purpose: Find a length of 'ptr' comprised of multi or single byte
724 *****************************************************************************/
726 _DtHelpFmtFindBreak (
736 while (0 == done && '\0' != *ptr)
738 mySize = mblen(ptr, MB_CUR_MAX);
741 ((1 != mb_len && 1 != mySize) || (1 == mb_len && 1 == mySize)))
750 *num_chars = numChars;
754 /******************************************************************************
755 * Function: _DtHelpLoadMultiInfo
757 * Returns: Loads the multi-byte formatting table for the current locale.
759 *****************************************************************************/
761 _DtHelpLoadMultiInfo (
762 wchar_t **cant_begin_chars,
763 wchar_t **cant_end_chars,
766 #ifndef NO_MESSAGE_CATALOG
771 cat_fd = catopen ("fmt_tbl", NL_CAT_LOCALE);
772 if (cat_fd != ((nl_catd) -1))
775 * Get the list of characters that can't begin a line.
777 ptr = catgets (cat_fd, 1, 1, "");
778 len = strlen (ptr) + 1;
779 *cant_begin_chars = (wchar_t *) malloc (len * sizeof (wchar_t));
780 if (NULL != *cant_begin_chars &&
781 mbstowcs(*cant_begin_chars, ptr, len) == -1)
783 free (*cant_begin_chars);
784 *cant_begin_chars = NULL;
788 * Get the list of characters that can't end a line.
790 ptr = catgets (cat_fd, 1, 2, "");
791 len = strlen (ptr) + 1;
792 *cant_end_chars = (wchar_t *) malloc (len * sizeof (wchar_t));
793 if (*cant_end_chars != NULL &&
794 mbstowcs(*cant_end_chars, ptr, len) == -1)
796 free (*cant_end_chars);
797 *cant_end_chars = NULL;
801 * Get the spacing flag. I.E. when does a internal newline
802 * get turned into a space.
803 * 1 means all the time.
804 * 0 means only between a multibyte string and
805 * a singlebyte string.
807 ptr = catgets (cat_fd, 1, 3, "1");
808 *nl_to_space = atoi(ptr);
815 *cant_begin_chars = NULL;
816 *cant_end_chars = NULL;