themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / vsnprintf.c
blobe1542f4d59a678dede50ef2117b8cc41821a1a7c
1 /*
2 * "$Id: vsnprintf.c 7903 2010-11-28 21:06:39Z matt $"
4 * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK).
6 * Copyright 1998-2010 by Bill Spitzak and others.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA.
23 * Please report all bugs and problems on the following page:
25 * http://www.fltk.org/str.php
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include "flstring.h"
33 #ifdef HAVE_SYS_STDTYPES_H
34 # include <sys/stdtypes.h>
35 #endif /* HAVE_SYS_STDTYPES_H */
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
41 int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) {
42 char *bufptr, /* Pointer to position in buffer */
43 *bufend, /* Pointer to end of buffer */
44 sign, /* Sign of format width */
45 size, /* Size character (h, l, L) */
46 type; /* Format type character */
47 int width, /* Width of field */
48 prec; /* Number of characters of precision */
49 char tformat[100], /* Temporary format string for sprintf() */
50 *tptr, /* Pointer into temporary format */
51 temp[1024]; /* Buffer for formatted numbers */
52 char *s; /* Pointer to string */
53 int slen; /* Length of string */
54 int bytes; /* Total number of bytes needed */
58 * Loop through the format string, formatting as needed...
61 bufptr = buffer;
62 bufend = buffer + bufsize - 1;
63 bytes = 0;
65 while (*format) {
66 if (*format == '%') {
67 tptr = tformat;
68 *tptr++ = *format++;
70 if (*format == '%') {
71 if (bufptr && bufptr < bufend) *bufptr++ = *format;
72 bytes ++;
73 format ++;
74 continue;
75 } else if (strchr(" -+#\'", *format)) {
76 *tptr++ = *format;
77 sign = *format++;
78 } else sign = 0;
80 if (*format == '*') {
81 /* Get width from argument... */
82 format ++;
83 width = va_arg(ap, int);
84 snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
85 tptr += strlen(tptr);
86 } else {
87 width = 0;
88 while (isdigit(*format & 255)) {
89 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
90 width = width * 10 + *format++ - '0';
94 if (*format == '.') {
95 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
96 format ++;
98 if (*format == '*') {
99 /* Get precision from argument... */
100 format ++;
101 prec = va_arg(ap, int);
102 snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
103 tptr += strlen(tptr);
104 } else {
105 prec = 0;
106 while (isdigit(*format & 255)) {
107 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
108 prec = prec * 10 + *format++ - '0';
111 } else prec = -1;
113 size = '\0';
115 if (*format == 'l' && format[1] == 'l') {
116 size = 'L';
117 if (tptr < (tformat + sizeof(tformat) - 2)) {
118 *tptr++ = 'l';
119 *tptr++ = 'l';
121 format += 2;
122 } else if (*format == 'h' || *format == 'l' || *format == 'L') {
123 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
124 size = *format++;
127 if (!*format) break;
129 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
130 type = *format++;
131 *tptr = '\0';
133 switch (type) {
134 case 'E' : /* Floating point formats */
135 case 'G' :
136 case 'e' :
137 case 'f' :
138 case 'g' :
139 if ((width + 2) > sizeof(temp)) break;
141 sprintf(temp, tformat, va_arg(ap, double));
143 bytes += strlen(temp);
145 if (bufptr) {
146 if ((bufptr + strlen(temp)) > bufend) {
147 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
148 bufptr = bufend;
149 } else {
150 strcpy(bufptr, temp);
151 bufptr += strlen(temp);
154 break;
156 case 'B' : /* Integer formats */
157 case 'X' :
158 case 'b' :
159 case 'd' :
160 case 'i' :
161 case 'o' :
162 case 'u' :
163 case 'x' :
164 if ((width + 2) > sizeof(temp)) break;
166 #ifdef HAVE_LONG_LONG
167 if (size == 'L')
168 sprintf(temp, tformat, va_arg(ap, long long));
169 else
170 #endif /* HAVE_LONG_LONG */
171 if (size == 'l')
172 sprintf(temp, tformat, va_arg(ap, long));
173 else
174 sprintf(temp, tformat, va_arg(ap, int));
176 bytes += strlen(temp);
178 if (bufptr) {
179 if ((bufptr + strlen(temp)) > bufend) {
180 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
181 bufptr = bufend;
182 } else {
183 strcpy(bufptr, temp);
184 bufptr += strlen(temp);
187 break;
189 case 'p' : /* Pointer value */
190 if ((width + 2) > sizeof(temp)) break;
192 sprintf(temp, tformat, va_arg(ap, void *));
194 bytes += strlen(temp);
196 if (bufptr) {
197 if ((bufptr + strlen(temp)) > bufend) {
198 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
199 bufptr = bufend;
200 } else {
201 strcpy(bufptr, temp);
202 bufptr += strlen(temp);
205 break;
207 case 'c' : /* Character or character array */
208 bytes += width;
210 if (bufptr) {
211 if (width <= 1) *bufptr++ = va_arg(ap, int);
212 else {
213 if ((bufptr + width) > bufend) width = bufend - bufptr;
215 memcpy(bufptr, va_arg(ap, char *), (size_t)width);
216 bufptr += width;
219 break;
221 case 's' : /* String */
222 if ((s = va_arg(ap, char *)) == NULL) s = "(null)";
224 slen = strlen(s);
225 if (slen > width && prec != width) width = slen;
227 bytes += width;
229 if (bufptr) {
230 if ((bufptr + width) > bufend) width = bufend - bufptr;
232 if (slen > width) slen = width;
234 if (sign == '-') {
235 strncpy(bufptr, s, (size_t)slen);
236 memset(bufptr + slen, ' ', (size_t)(width - slen));
237 } else {
238 memset(bufptr, ' ', (size_t)(width - slen));
239 strncpy(bufptr + width - slen, s, (size_t)slen);
242 bufptr += width;
244 break;
246 case 'n' : /* Output number of chars so far */
247 *(va_arg(ap, int *)) = bytes;
248 break;
250 } else {
251 bytes ++;
253 if (bufptr && bufptr < bufend) *bufptr++ = *format;
254 format ++;
259 * Nul-terminate the string and return the number of characters needed.
262 if (bufptr) *bufptr = '\0';
264 return (bytes);
267 int fl_snprintf(char* str, size_t size, const char* fmt, ...) {
268 int ret;
269 va_list ap;
270 va_start(ap, fmt);
271 ret = vsnprintf(str, size, fmt, ap);
272 va_end(ap);
273 return ret;
276 #ifdef __cplusplus
278 #endif
281 * End of "$Id: vsnprintf.c 7903 2010-11-28 21:06:39Z matt $".