File: | core/misc.c |
Location: | line 799, column 3 |
Description: | Value stored to 'dest' is never read |
1 | /* |
2 | misc.c : irssi |
3 | |
4 | Copyright (C) 1999 Timo Sirainen |
5 | |
6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 2 of the License, or |
9 | (at your option) any later version. |
10 | |
11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License along |
17 | with this program; if not, write to the Free Software Foundation, Inc., |
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ |
20 | |
21 | #include "module.h" |
22 | #include "misc.h" |
23 | |
24 | #ifdef HAVE_REGEX_H1 |
25 | # include <regex.h> |
26 | #endif |
27 | |
28 | typedef struct { |
29 | int condition; |
30 | GInputFunction function; |
31 | void *data; |
32 | } IRSSI_INPUT_REC; |
33 | |
34 | static int irssi_io_invoke(GIOChannel *source, GIOCondition condition, |
35 | void *data) |
36 | { |
37 | IRSSI_INPUT_REC *rec = data; |
38 | int icond = 0; |
39 | |
40 | if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) { |
41 | /* error, we have to call the function.. */ |
42 | if (rec->condition & G_IO_IN) |
43 | icond |= G_INPUT_READ(1 << 0); |
44 | else |
45 | icond |= G_INPUT_WRITE(1 << 1); |
46 | } |
47 | |
48 | if (condition & (G_IO_IN | G_IO_PRI)) |
49 | icond |= G_INPUT_READ(1 << 0); |
50 | if (condition & G_IO_OUT) |
51 | icond |= G_INPUT_WRITE(1 << 1); |
52 | |
53 | if (rec->condition & icond) |
54 | rec->function(rec->data, source, icond); |
55 | |
56 | return TRUE(!(0)); |
57 | } |
58 | |
59 | int g_input_add_full(GIOChannel *source, int priority, int condition, |
60 | GInputFunction function, void *data) |
61 | { |
62 | IRSSI_INPUT_REC *rec; |
63 | unsigned int result; |
64 | GIOCondition cond; |
65 | |
66 | rec = g_new(IRSSI_INPUT_REC, 1)((IRSSI_INPUT_REC *) g_malloc (((gsize) sizeof (IRSSI_INPUT_REC )) * ((gsize) (1)))); |
67 | rec->condition = condition; |
68 | rec->function = function; |
69 | rec->data = data; |
70 | |
71 | cond = (GIOCondition) (G_IO_ERR|G_IO_HUP|G_IO_NVAL); |
72 | if (condition & G_INPUT_READ(1 << 0)) |
73 | cond |= G_IO_IN|G_IO_PRI; |
74 | if (condition & G_INPUT_WRITE(1 << 1)) |
75 | cond |= G_IO_OUT; |
76 | |
77 | result = g_io_add_watch_full(source, priority, cond, |
78 | irssi_io_invoke, rec, g_free); |
79 | |
80 | return result; |
81 | } |
82 | |
83 | int g_input_add(GIOChannel *source, int condition, |
84 | GInputFunction function, void *data) |
85 | { |
86 | return g_input_add_full(source, G_PRIORITY_DEFAULT0, condition, |
87 | function, data); |
88 | } |
89 | |
90 | /* easy way to bypass glib polling of io channel internal buffer */ |
91 | int g_input_add_poll(int fd, int priority, int condition, |
92 | GInputFunction function, void *data) |
93 | { |
94 | GIOChannel *source = g_io_channel_unix_new(fd); |
95 | int ret = g_input_add_full(source, priority, condition, function, data); |
96 | g_io_channel_unref(source); |
97 | return ret; |
98 | } |
99 | |
100 | int g_timeval_cmp(const GTimeVal *tv1, const GTimeVal *tv2) |
101 | { |
102 | if (tv1->tv_sec < tv2->tv_sec) |
103 | return -1; |
104 | if (tv1->tv_sec > tv2->tv_sec) |
105 | return 1; |
106 | |
107 | return tv1->tv_usec < tv2->tv_usec ? -1 : |
108 | tv1->tv_usec > tv2->tv_usec ? 1 : 0; |
109 | } |
110 | |
111 | long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2) |
112 | { |
113 | long secs, usecs; |
114 | |
115 | secs = tv1->tv_sec - tv2->tv_sec; |
116 | usecs = tv1->tv_usec - tv2->tv_usec; |
117 | if (usecs < 0) { |
118 | usecs += 1000000; |
119 | secs--; |
120 | } |
121 | usecs = usecs/1000 + secs * 1000; |
122 | |
123 | return usecs; |
124 | } |
125 | |
126 | int find_substr(const char *list, const char *item) |
127 | { |
128 | const char *ptr; |
129 | |
130 | g_return_val_if_fail(list != NULL, FALSE)do{ if (list != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "list != NULL"); return ( (0)); }; }while (0); |
131 | g_return_val_if_fail(item != NULL, FALSE)do{ if (item != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "item != NULL"); return ( (0)); }; }while (0); |
132 | |
133 | if (*item == '\0') |
134 | return FALSE(0); |
135 | |
136 | for (;;) { |
137 | while (i_isspace(*list)__sbistype(((int) (unsigned char) (*list)), 0x00004000L)) list++; |
138 | if (*list == '\0') break; |
139 | |
140 | ptr = strchr(list, ' '); |
141 | if (ptr == NULL((void *)0)) ptr = list+strlen(list); |
142 | |
143 | if (g_strncasecmp(list, item, ptr-list) == 0 && |
144 | item[ptr-list] == '\0') |
145 | return TRUE(!(0)); |
146 | |
147 | list = ptr; |
148 | } |
149 | |
150 | return FALSE(0); |
151 | } |
152 | |
153 | int strarray_length(char **array) |
154 | { |
155 | int len; |
156 | |
157 | g_return_val_if_fail(array != NULL, 0)do{ if (array != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "array != NULL"); return (0); }; }while (0); |
158 | |
159 | len = 0; |
160 | while (*array) { |
161 | len++; |
162 | array++; |
163 | } |
164 | return len; |
165 | } |
166 | |
167 | int strarray_find(char **array, const char *item) |
168 | { |
169 | char **tmp; |
170 | int index; |
171 | |
172 | g_return_val_if_fail(array != NULL, 0)do{ if (array != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "array != NULL"); return (0); }; }while (0); |
173 | g_return_val_if_fail(item != NULL, 0)do{ if (item != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "item != NULL"); return ( 0); }; }while (0); |
174 | |
175 | index = 0; |
176 | for (tmp = array; *tmp != NULL((void *)0); tmp++, index++) { |
177 | if (g_strcasecmp(*tmp, item) == 0) |
178 | return index; |
179 | } |
180 | |
181 | return -1; |
182 | } |
183 | |
184 | GSList *gslist_find_string(GSList *list, const char *key) |
185 | { |
186 | for (list = list; list != NULL((void *)0); list = list->next) |
187 | if (strcmp(list->data, key) == 0) return list; |
188 | |
189 | return NULL((void *)0); |
190 | } |
191 | |
192 | GSList *gslist_find_icase_string(GSList *list, const char *key) |
193 | { |
194 | for (list = list; list != NULL((void *)0); list = list->next) |
195 | if (g_strcasecmp(list->data, key) == 0) return list; |
196 | |
197 | return NULL((void *)0); |
198 | } |
199 | |
200 | void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, const void *data) |
201 | { |
202 | void *ret; |
203 | |
204 | while (list != NULL((void *)0)) { |
205 | ret = func(list->data, (void *) data); |
206 | if (ret != NULL((void *)0)) return ret; |
207 | |
208 | list = list->next; |
209 | } |
210 | |
211 | return NULL((void *)0); |
212 | } |
213 | |
214 | /* `list' contains pointer to structure with a char* to string. */ |
215 | char *gslistptr_to_string(GSList *list, int offset, const char *delimiter) |
216 | { |
217 | GString *str; |
218 | char **data, *ret; |
219 | |
220 | str = g_string_new(NULL((void *)0)); |
221 | while (list != NULL((void *)0)) { |
222 | data = G_STRUCT_MEMBER_P(list->data, offset)((gpointer) ((guint8*) (list->data) + (glong) (offset))); |
223 | |
224 | if (str->len != 0) g_string_append(str, delimiter); |
225 | g_string_append(str, *data); |
226 | list = list->next; |
227 | } |
228 | |
229 | ret = str->str; |
230 | g_string_free(str, FALSE(0)); |
231 | return ret; |
232 | } |
233 | |
234 | /* `list' contains char* */ |
235 | char *gslist_to_string(GSList *list, const char *delimiter) |
236 | { |
237 | GString *str; |
238 | char *ret; |
239 | |
240 | str = g_string_new(NULL((void *)0)); |
241 | while (list != NULL((void *)0)) { |
242 | if (str->len != 0) g_string_append(str, delimiter); |
243 | g_string_append(str, list->data); |
244 | |
245 | list = list->next; |
246 | } |
247 | |
248 | ret = str->str; |
249 | g_string_free(str, FALSE(0)); |
250 | return ret; |
251 | } |
252 | |
253 | void hash_save_key(char *key, void *value, GSList **list) |
254 | { |
255 | *list = g_slist_append(*list, key); |
256 | } |
257 | |
258 | /* save all keys in hash table to linked list - you shouldn't remove any |
259 | items while using this list, use g_slist_free() after you're done with it */ |
260 | GSList *hashtable_get_keys(GHashTable *hash) |
261 | { |
262 | GSList *list; |
263 | |
264 | list = NULL((void *)0); |
265 | g_hash_table_foreach(hash, (GHFunc) hash_save_key, &list); |
266 | return list; |
267 | } |
268 | |
269 | GList *glist_find_string(GList *list, const char *key) |
270 | { |
271 | for (list = list; list != NULL((void *)0); list = list->next) |
272 | if (strcmp(list->data, key) == 0) return list; |
273 | |
274 | return NULL((void *)0); |
275 | } |
276 | |
277 | GList *glist_find_icase_string(GList *list, const char *key) |
278 | { |
279 | for (list = list; list != NULL((void *)0); list = list->next) |
280 | if (g_strcasecmp(list->data, key) == 0) return list; |
281 | |
282 | return NULL((void *)0); |
283 | } |
284 | |
285 | char *stristr(const char *data, const char *key) |
286 | { |
287 | const char *max; |
288 | int keylen, datalen, pos; |
289 | |
290 | keylen = strlen(key); |
291 | datalen = strlen(data); |
292 | |
293 | if (keylen > datalen) |
294 | return NULL((void *)0); |
295 | if (keylen == 0) |
296 | return (char *) data; |
297 | |
298 | max = data+datalen-keylen; |
299 | pos = 0; |
300 | while (data <= max) { |
301 | if (key[pos] == '\0') |
302 | return (char *) data; |
303 | |
304 | if (i_toupper(data[pos])__sbtoupper((int) (unsigned char) (data[pos])) == i_toupper(key[pos])__sbtoupper((int) (unsigned char) (key[pos]))) |
305 | pos++; |
306 | else { |
307 | data++; |
308 | pos = 0; |
309 | } |
310 | } |
311 | |
312 | return NULL((void *)0); |
313 | } |
314 | |
315 | #define isbound(c)((unsigned char) (c) < 128 && (__sbistype(((int) ( unsigned char) (c)), 0x00004000L) || __sbistype(((int) (unsigned char) (c)), 0x00002000L))) \ |
316 | ((unsigned char) (c) < 128 && \ |
317 | (i_isspace(c)__sbistype(((int) (unsigned char) (c)), 0x00004000L) || i_ispunct(c)__sbistype(((int) (unsigned char) (c)), 0x00002000L))) |
318 | |
319 | static char *strstr_full_case(const char *data, const char *key, int icase) |
320 | { |
321 | const char *start, *max; |
322 | int keylen, datalen, pos, match; |
323 | |
324 | keylen = strlen(key); |
325 | datalen = strlen(data); |
326 | |
327 | if (keylen > datalen) |
328 | return NULL((void *)0); |
329 | if (keylen == 0) |
330 | return (char *) data; |
331 | |
332 | max = data+datalen-keylen; |
333 | start = data; pos = 0; |
334 | while (data <= max) { |
335 | if (key[pos] == '\0') { |
336 | if (data[pos] != '\0' && !isbound(data[pos])((unsigned char) (data[pos]) < 128 && (__sbistype( ((int) (unsigned char) (data[pos])), 0x00004000L) || __sbistype (((int) (unsigned char) (data[pos])), 0x00002000L)))) { |
337 | data++; |
338 | pos = 0; |
339 | continue; |
340 | } |
341 | return (char *) data; |
342 | } |
343 | |
344 | match = icase ? (i_toupper(data[pos])__sbtoupper((int) (unsigned char) (data[pos])) == i_toupper(key[pos])__sbtoupper((int) (unsigned char) (key[pos]))) : |
345 | data[pos] == key[pos]; |
346 | |
347 | if (match && (pos != 0 || data == start || isbound(data[-1])((unsigned char) (data[-1]) < 128 && (__sbistype(( (int) (unsigned char) (data[-1])), 0x00004000L) || __sbistype (((int) (unsigned char) (data[-1])), 0x00002000L))))) |
348 | pos++; |
349 | else { |
350 | data++; |
351 | pos = 0; |
352 | } |
353 | } |
354 | |
355 | return NULL((void *)0); |
356 | } |
357 | |
358 | char *strstr_full(const char *data, const char *key) |
359 | { |
360 | return strstr_full_case(data, key, FALSE(0)); |
361 | } |
362 | |
363 | char *stristr_full(const char *data, const char *key) |
364 | { |
365 | return strstr_full_case(data, key, TRUE(!(0))); |
366 | } |
367 | |
368 | int regexp_match(const char *str, const char *regexp) |
369 | { |
370 | #ifdef HAVE_REGEX_H1 |
371 | regex_t preg; |
372 | int ret; |
373 | |
374 | if (regcomp(&preg, regexp, REG_EXTENDED0001|REG_ICASE0002|REG_NOSUB0004) != 0) |
375 | return 0; |
376 | |
377 | ret = regexec(&preg, str, 0, NULL((void *)0), 0); |
378 | regfree(&preg); |
379 | |
380 | return ret == 0; |
381 | #else |
382 | return FALSE(0); |
383 | #endif |
384 | } |
385 | |
386 | /* Create the directory and all it's parent directories */ |
387 | int mkpath(const char *path, int mode) |
388 | { |
389 | struct stat statbuf; |
390 | const char *p; |
391 | char *dir; |
392 | |
393 | g_return_val_if_fail(path != NULL, -1)do{ if (path != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "path != NULL"); return ( -1); }; }while (0); |
394 | |
395 | p = g_path_skip_root((char *) path); |
396 | if (p == NULL((void *)0)) { |
397 | /* not a full path, maybe not what we wanted |
398 | but continue anyway.. */ |
399 | p = path; |
400 | } |
401 | for (;;) { |
402 | if (*p != G_DIR_SEPARATOR'/' && *p != '\0') { |
403 | p++; |
404 | continue; |
405 | } |
406 | |
407 | dir = g_strndup(path, (int) (p-path)); |
408 | if (stat(dir, &statbuf) != 0) { |
409 | #ifndef WIN32 |
410 | if (mkdir(dir, mode) == -1) |
411 | #else |
412 | if (_mkdir(dir) == -1) |
413 | #endif |
414 | { |
415 | g_free(dir); |
416 | return -1; |
417 | } |
418 | } |
419 | g_free(dir); |
420 | |
421 | if (*p++ == '\0') |
422 | break; |
423 | } |
424 | |
425 | return 0; |
426 | } |
427 | |
428 | /* convert ~/ to $HOME */ |
429 | char *convert_home(const char *path) |
430 | { |
431 | const char *home; |
432 | |
433 | if (*path == '~' && (*(path+1) == '/' || *(path+1) == '\0')) { |
434 | home = g_get_home_dir(); |
435 | if (home == NULL((void *)0)) |
436 | home = "."; |
437 | |
438 | return g_strconcat(home, path+1, NULL((void *)0)); |
439 | } else { |
440 | return g_strdup(path); |
441 | } |
442 | } |
443 | |
444 | int g_istr_equal(gconstpointer v, gconstpointer v2) |
445 | { |
446 | return g_strcasecmp((const char *) v, (const char *) v2) == 0; |
447 | } |
448 | |
449 | int g_istr_cmp(gconstpointer v, gconstpointer v2) |
450 | { |
451 | return g_strcasecmp((const char *) v, (const char *) v2); |
452 | } |
453 | |
454 | /* a char* hash function from ASU */ |
455 | unsigned int g_istr_hash(gconstpointer v) |
456 | { |
457 | const char *s = (const char *) v; |
458 | unsigned int h = 0, g; |
459 | |
460 | while (*s != '\0') { |
461 | h = (h << 4) + i_toupper(*s)__sbtoupper((int) (unsigned char) (*s)); |
462 | if ((g = h & 0xf0000000UL)) { |
463 | h = h ^ (g >> 24); |
464 | h = h ^ g; |
465 | } |
466 | s++; |
467 | } |
468 | |
469 | return h /* % M */; |
470 | } |
471 | |
472 | /* Find `mask' from `data', you can use * and ? wildcards. */ |
473 | int match_wildcards(const char *cmask, const char *data) |
474 | { |
475 | char *mask, *newmask, *p1, *p2; |
476 | int ret; |
477 | |
478 | newmask = mask = g_strdup(cmask); |
479 | for (; *mask != '\0' && *data != '\0'; mask++) { |
480 | if (*mask != '*') { |
481 | if (*mask != '?' && i_toupper(*mask)__sbtoupper((int) (unsigned char) (*mask)) != i_toupper(*data)__sbtoupper((int) (unsigned char) (*data))) |
482 | break; |
483 | |
484 | data++; |
485 | continue; |
486 | } |
487 | |
488 | while (*mask == '?' || *mask == '*') mask++; |
489 | if (*mask == '\0') { |
490 | data += strlen(data); |
491 | break; |
492 | } |
493 | |
494 | p1 = strchr(mask, '*'); |
495 | p2 = strchr(mask, '?'); |
496 | if (p1 == NULL((void *)0) || (p2 < p1 && p2 != NULL((void *)0))) p1 = p2; |
497 | |
498 | if (p1 != NULL((void *)0)) *p1 = '\0'; |
499 | |
500 | data = stristr(data, mask); |
501 | if (data == NULL((void *)0)) break; |
502 | |
503 | data += strlen(mask); |
504 | mask += strlen(mask)-1; |
505 | |
506 | if (p1 != NULL((void *)0)) *p1 = p1 == p2 ? '?' : '*'; |
507 | } |
508 | |
509 | while (*mask == '*') mask++; |
510 | |
511 | ret = data != NULL((void *)0) && *data == '\0' && *mask == '\0'; |
512 | g_free(newmask); |
513 | |
514 | return ret; |
515 | } |
516 | |
517 | /* Return TRUE if all characters in `str' are numbers. |
518 | Stop when `end_char' is found from string. */ |
519 | int is_numeric(const char *str, char end_char) |
520 | { |
521 | g_return_val_if_fail(str != NULL, FALSE)do{ if (str != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "str != NULL"); return ( (0)); }; }while (0); |
522 | |
523 | if (*str == '\0' || *str == end_char) |
524 | return FALSE(0); |
525 | |
526 | while (*str != '\0' && *str != end_char) { |
527 | if (!i_isdigit(*str)__isctype(((int) (unsigned char) (*str)), 0x00000400L)) return FALSE(0); |
528 | str++; |
529 | } |
530 | |
531 | return TRUE(!(0)); |
532 | } |
533 | |
534 | /* replace all `from' chars in string to `to' chars. returns `str' */ |
535 | char *replace_chars(char *str, char from, char to) |
536 | { |
537 | char *p; |
538 | |
539 | for (p = str; *p != '\0'; p++) { |
540 | if (*p == from) *p = to; |
541 | } |
542 | return str; |
543 | } |
544 | |
545 | int octal2dec(int octal) |
546 | { |
547 | int dec, n; |
548 | |
549 | dec = 0; n = 1; |
550 | while (octal != 0) { |
551 | dec += n*(octal%10); |
552 | octal /= 10; n *= 8; |
553 | } |
554 | |
555 | return dec; |
556 | } |
557 | |
558 | int dec2octal(int decimal) |
559 | { |
560 | int octal, pos; |
561 | |
562 | octal = 0; pos = 0; |
563 | while (decimal > 0) { |
564 | octal += (decimal & 7)*(pos == 0 ? 1 : pos); |
565 | decimal /= 8; |
566 | pos += 10; |
567 | } |
568 | |
569 | return octal; |
570 | } |
571 | |
572 | /* string -> uoff_t */ |
573 | uoff_t str_to_uofft(const char *str) |
574 | { |
575 | uoff_t ret; |
576 | |
577 | ret = 0; |
578 | while (*str != '\0') { |
579 | ret = ret*10 + (*str - '0'); |
580 | str++; |
581 | } |
582 | |
583 | return ret; |
584 | } |
585 | |
586 | /* convert all low-ascii (<32) to ^<A..> combinations */ |
587 | char *show_lowascii(const char *str) |
588 | { |
589 | char *ret, *p; |
590 | |
591 | ret = p = g_malloc(strlen(str)*2+1); |
592 | while (*str != '\0') { |
593 | if ((unsigned char) *str >= 32) |
594 | *p++ = *str; |
595 | else { |
596 | *p++ = '^'; |
597 | *p++ = *str + 'A'-1; |
598 | } |
599 | str++; |
600 | } |
601 | *p = '\0'; |
602 | |
603 | return ret; |
604 | } |
605 | |
606 | /* Get time in human readable form with localtime() + asctime() */ |
607 | char *my_asctime(time_t t) |
608 | { |
609 | struct tm *tm; |
610 | char *str; |
611 | int len; |
612 | |
613 | tm = localtime(&t); |
614 | str = g_strdup(asctime(tm)); |
615 | |
616 | len = strlen(str); |
617 | if (len > 0) str[len-1] = '\0'; |
618 | return str; |
619 | } |
620 | |
621 | /* Returns number of columns needed to print items. |
622 | save_column_widths is filled with length of each column. */ |
623 | int get_max_column_count(GSList *items, COLUMN_LEN_FUNC len_func, |
624 | int max_width, int max_columns, |
625 | int item_extra, int item_min_size, |
626 | int **save_column_widths, int *rows) |
627 | { |
628 | GSList *tmp; |
629 | int **columns, *columns_width, *columns_rows; |
630 | int item_pos, items_count; |
631 | int ret, len, max_len, n, col; |
632 | |
633 | items_count = g_slist_length(items); |
634 | if (items_count == 0) { |
635 | *save_column_widths = NULL((void *)0); |
636 | *rows = 0; |
637 | return 0; |
638 | } |
639 | |
640 | len = max_width/(item_extra+item_min_size); |
641 | if (len <= 0) len = 1; |
642 | if (max_columns <= 0 || len < max_columns) |
643 | max_columns = len; |
644 | |
645 | columns = g_new0(int *, max_columns)((int * *) g_malloc0 (((gsize) sizeof (int *)) * ((gsize) (max_columns )))); |
646 | columns_width = g_new0(int, max_columns)((int *) g_malloc0 (((gsize) sizeof (int)) * ((gsize) (max_columns )))); |
647 | columns_rows = g_new0(int, max_columns)((int *) g_malloc0 (((gsize) sizeof (int)) * ((gsize) (max_columns )))); |
648 | |
649 | for (n = 1; n < max_columns; n++) { |
650 | columns[n] = g_new0(int, n+1)((int *) g_malloc0 (((gsize) sizeof (int)) * ((gsize) (n+1))) ); |
651 | columns_rows[n] = items_count <= n+1 ? 1 : |
652 | (items_count+n)/(n+1); |
653 | } |
654 | |
655 | /* for each possible column count, save the column widths and |
656 | find the biggest column count that fits to screen. */ |
657 | item_pos = 0; max_len = 0; |
658 | for (tmp = items; tmp != NULL((void *)0); tmp = tmp->next) { |
659 | len = item_extra+len_func(tmp->data); |
660 | if (max_len < len) |
661 | max_len = len; |
662 | |
663 | for (n = 1; n < max_columns; n++) { |
664 | if (columns_width[n] > max_width) |
665 | continue; /* too wide */ |
666 | |
667 | col = item_pos/columns_rows[n]; |
668 | if (columns[n][col] < len) { |
669 | columns_width[n] += len-columns[n][col]; |
670 | columns[n][col] = len; |
671 | } |
672 | } |
673 | |
674 | item_pos++; |
675 | } |
676 | |
677 | for (n = max_columns-1; n >= 1; n--) { |
678 | if (columns_width[n] <= max_width && |
679 | columns[n][n] > 0) |
680 | break; |
681 | } |
682 | ret = n+1; |
683 | |
684 | *save_column_widths = g_new(int, ret)((int *) g_malloc (((gsize) sizeof (int)) * ((gsize) (ret)))); |
685 | if (ret == 1) { |
686 | **save_column_widths = max_len; |
687 | *rows = 1; |
688 | } else { |
689 | memcpy(*save_column_widths, columns[ret-1], sizeof(int)*ret); |
690 | *rows = columns_rows[ret-1]; |
691 | } |
692 | |
693 | for (n = 1; n < max_columns; n++) |
694 | g_free(columns[n]); |
695 | g_free(columns_width); |
696 | g_free(columns_rows); |
697 | g_free(columns); |
698 | |
699 | return ret; |
700 | } |
701 | |
702 | /* Return a column sorted copy of a list. */ |
703 | GSList *columns_sort_list(GSList *list, int rows) |
704 | { |
705 | GSList *tmp, *sorted; |
706 | int row, skip; |
707 | |
708 | if (list == NULL((void *)0) || rows == 0) |
709 | return list; |
710 | |
711 | sorted = NULL((void *)0); |
712 | |
713 | for (row = 0; row < rows; row++) { |
714 | tmp = g_slist_nth(list, row); |
715 | skip = 1; |
716 | for (; tmp != NULL((void *)0); tmp = tmp->next) { |
717 | if (--skip == 0) { |
718 | skip = rows; |
719 | sorted = g_slist_append(sorted, tmp->data); |
720 | } |
721 | } |
722 | } |
723 | |
724 | g_return_val_if_fail(g_slist_length(sorted) ==do{ if (g_slist_length(sorted) == g_slist_length(list)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__ , "g_slist_length(sorted) == g_slist_length(list)"); return ( sorted); }; }while (0) |
725 | g_slist_length(list), sorted)do{ if (g_slist_length(sorted) == g_slist_length(list)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__ , "g_slist_length(sorted) == g_slist_length(list)"); return ( sorted); }; }while (0); |
726 | return sorted; |
727 | } |
728 | |
729 | /* Expand escape string, the first character in data should be the |
730 | one after '\'. Returns the expanded character or -1 if error. */ |
731 | int expand_escape(const char **data) |
732 | { |
733 | char digit[4]; |
734 | |
735 | switch (**data) { |
736 | case 't': |
737 | return '\t'; |
738 | case 'r': |
739 | return '\r'; |
740 | case 'n': |
741 | return '\n'; |
742 | case 'e': |
743 | return 27; /* ESC */ |
744 | |
745 | case 'x': |
746 | /* hex digit */ |
747 | if (!i_isxdigit((*data)[1])__isctype(((int) (unsigned char) ((*data)[1])), 0x00010000L) || !i_isxdigit((*data)[2])__isctype(((int) (unsigned char) ((*data)[2])), 0x00010000L)) |
748 | return -1; |
749 | |
750 | digit[0] = (*data)[1]; |
751 | digit[1] = (*data)[2]; |
752 | digit[2] = '\0'; |
753 | *data += 2; |
754 | return strtol(digit, NULL((void *)0), 16); |
755 | case 'c': |
756 | /* control character (\cA = ^A) */ |
757 | (*data)++; |
758 | return i_toupper(**data)__sbtoupper((int) (unsigned char) (**data)) - 64; |
759 | default: |
760 | if (!i_isdigit(**data)__isctype(((int) (unsigned char) (**data)), 0x00000400L)) |
761 | return -1; |
762 | |
763 | /* octal */ |
764 | digit[0] = (*data)[0]; |
765 | digit[1] = (*data)[1]; |
766 | digit[2] = (*data)[2]; |
767 | digit[3] = '\0'; |
768 | *data += 2; |
769 | return strtol(digit, NULL((void *)0), 8); |
770 | } |
771 | } |
772 | |
773 | /* Escape all '"', "'" and '\' chars with '\' */ |
774 | char *escape_string(const char *str) |
775 | { |
776 | char *ret, *p; |
777 | |
778 | p = ret = g_malloc(strlen(str)*2+1); |
779 | while (*str != '\0') { |
780 | if (*str == '"' || *str == '\'' || *str == '\\') |
781 | *p++ = '\\'; |
782 | *p++ = *str++; |
783 | } |
784 | *p = '\0'; |
785 | |
786 | return ret; |
787 | } |
788 | |
789 | int strocpy(char *dest, const char *src, size_t dstsize) |
790 | { |
791 | if (dstsize == 0) |
792 | return -1; |
793 | |
794 | while (*src != '\0' && dstsize > 1) { |
795 | *dest++ = *src++; |
796 | dstsize--; |
797 | } |
798 | |
799 | *dest++ = '\0'; |
Value stored to 'dest' is never read | |
800 | return *src == '\0' ? 0 : -1; |
801 | } |
802 | |
803 | int nearest_power(int num) |
804 | { |
805 | int n = 1; |
806 | |
807 | while (n < num) n <<= 1; |
808 | return n; |
809 | } |
810 | |
811 | int parse_time_interval(const char *time, int *msecs) |
812 | { |
813 | const char *desc; |
814 | int number, sign, len, ret; |
815 | |
816 | *msecs = 0; |
817 | |
818 | /* max. return value is around 24 days */ |
819 | number = 0; sign = 1; ret = TRUE(!(0)); |
820 | for (;;) { |
821 | if (*time == '-') { |
822 | sign = -sign; |
823 | time++; |
824 | continue; |
825 | } |
826 | |
827 | if (i_isdigit(*time)__isctype(((int) (unsigned char) (*time)), 0x00000400L)) { |
828 | number = number*10 + (*time - '0'); |
829 | time++; |
830 | continue; |
831 | } |
832 | |
833 | /* skip punctuation */ |
834 | while (*time != '\0' && i_ispunct(*time)__sbistype(((int) (unsigned char) (*time)), 0x00002000L)) |
835 | time++; |
836 | |
837 | /* get description */ |
838 | for (len = 0, desc = time; i_isalpha(*time)__sbistype(((int) (unsigned char) (*time)), 0x00000100L); time++) |
839 | len++; |
840 | |
841 | if (len == 0) { |
842 | *msecs += number * 1000; /* assume seconds */ |
843 | *msecs *= sign; |
844 | return TRUE(!(0)); |
845 | } |
846 | |
847 | if (g_ascii_strncasecmp(desc, "days", len) == 0) { |
848 | if (number > 24) { |
849 | /* would overflow */ |
850 | return FALSE(0); |
851 | } |
852 | *msecs += number * 1000*3600*24; |
853 | } else if (g_ascii_strncasecmp(desc, "hours", len) == 0) |
854 | *msecs += number * 1000*3600; |
855 | else if (g_ascii_strncasecmp(desc, "minutes", len) == 0 || |
856 | g_ascii_strncasecmp(desc, "mins", len) == 0) |
857 | *msecs += number * 1000*60; |
858 | else if (g_ascii_strncasecmp(desc, "seconds", len) == 0 || |
859 | g_ascii_strncasecmp(desc, "secs", len) == 0) |
860 | *msecs += number * 1000; |
861 | else if (g_ascii_strncasecmp(desc, "milliseconds", len) == 0 || |
862 | g_ascii_strncasecmp(desc, "millisecs", len) == 0 || |
863 | g_ascii_strncasecmp(desc, "mseconds", len) == 0 || |
864 | g_ascii_strncasecmp(desc, "msecs", len) == 0) |
865 | *msecs += number; |
866 | else { |
867 | ret = FALSE(0); |
868 | } |
869 | |
870 | /* skip punctuation */ |
871 | while (*time != '\0' && i_ispunct(*time)__sbistype(((int) (unsigned char) (*time)), 0x00002000L)) |
872 | time++; |
873 | |
874 | if (*time == '\0') |
875 | break; |
876 | |
877 | number = 0; |
878 | } |
879 | |
880 | *msecs *= sign; |
881 | return ret; |
882 | } |
883 | |
884 | int parse_size(const char *size, int *bytes) |
885 | { |
886 | const char *desc; |
887 | int number, len; |
888 | |
889 | *bytes = 0; |
890 | |
891 | /* max. return value is about 1.6 years */ |
892 | number = 0; |
893 | while (*size != '\0') { |
894 | if (i_isdigit(*size)__isctype(((int) (unsigned char) (*size)), 0x00000400L)) { |
895 | number = number*10 + (*size - '0'); |
896 | size++; |
897 | continue; |
898 | } |
899 | |
900 | /* skip punctuation */ |
901 | while (*size != '\0' && i_ispunct(*size)__sbistype(((int) (unsigned char) (*size)), 0x00002000L)) |
902 | size++; |
903 | |
904 | /* get description */ |
905 | for (len = 0, desc = size; i_isalpha(*size)__sbistype(((int) (unsigned char) (*size)), 0x00000100L); size++) |
906 | len++; |
907 | |
908 | if (len == 0) { |
909 | if (number == 0) { |
910 | /* "0" - allow it */ |
911 | return TRUE(!(0)); |
912 | } |
913 | |
914 | *bytes += number*1024; /* assume kilobytes */ |
915 | return FALSE(0); |
916 | } |
917 | |
918 | if (g_ascii_strncasecmp(desc, "gbytes", len) == 0) |
919 | *bytes += number * 1024*1024*1024; |
920 | if (g_ascii_strncasecmp(desc, "mbytes", len) == 0) |
921 | *bytes += number * 1024*1024; |
922 | if (g_ascii_strncasecmp(desc, "kbytes", len) == 0) |
923 | *bytes += number * 1024; |
924 | if (g_ascii_strncasecmp(desc, "bytes", len) == 0) |
925 | *bytes += number; |
926 | |
927 | /* skip punctuation */ |
928 | while (*size != '\0' && i_ispunct(*size)__sbistype(((int) (unsigned char) (*size)), 0x00002000L)) |
929 | size++; |
930 | } |
931 | |
932 | return TRUE(!(0)); |
933 | } |