]> www.fi.muni.cz Git - evince.git/blob - backend/dvi/mdvi-lib/util.c
788b7744cf7d09f4ecfac4e6233cd566ba396b62
[evince.git] / backend / dvi / mdvi-lib / util.c
1 /*
2  * Copyright (C) 2000, Matias Atria
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <time.h>
24 #include <sys/stat.h>
25 #include <errno.h>
26 #include <unistd.h>
27
28 #include "common.h"
29 #include "private.h"
30
31 static char *const messages[] = {
32         _G("Ooops!"),
33         _G("Aieeeee!!"),
34         _G("Ouch!"),
35         _G("Houston, we have a problem"),
36         _G("3.. 2.. 1.. BOOM!"),
37         _G("I'm history"),
38         _G("I'm going down"),
39         _G("I smell a rat")
40 };
41 #define NMSGS   (sizeof(messages) / sizeof(char *))
42
43 static FILE *logfile = NULL;
44 static int _mdvi_log_level;
45
46 int mdvi_set_logfile(const char *filename);
47 int mdvi_set_logstream(FILE *file);
48 int mdvi_set_loglevel(int level);
49
50 static void vputlog(int level, const char *head, const char *format, va_list ap)
51 {
52         if(logfile != NULL && _mdvi_log_level >= level) {
53                 if(head != NULL)
54                         fprintf(logfile, "%s: ", head);
55                 vfprintf(logfile, format, ap);
56         }
57 }
58
59 int mdvi_set_logfile(const char *filename)
60 {
61         FILE    *f = NULL;
62
63         if(filename && (f = fopen(filename, "w")) == NULL)
64                 return -1;
65         if(logfile != NULL && !isatty(fileno(logfile))) {
66                 fclose(logfile);
67                 logfile = NULL;
68         }
69         if(filename)
70                 logfile = f;
71         return 0;
72 }
73
74 int mdvi_set_logstream(FILE *file)
75 {
76         if(logfile && !isatty(fileno(logfile))) {
77                 fclose(logfile);
78                 logfile = NULL;
79         }
80         logfile = file;
81         return 0;
82 }
83
84 int mdvi_set_loglevel(int level)
85 {
86         int     old = _mdvi_log_level;
87         
88         _mdvi_log_level = level;
89         return old;
90 }
91
92 #ifndef NODEBUG
93 Uint32 _mdvi_debug_mask = 0;
94
95 void    __debug(int mask, const char *format, ...)
96 {
97         va_list ap;
98         
99         va_start(ap, format);
100         if(_mdvi_debug_mask & mask) {
101                 if(!DEBUGGING(SILENT)) {
102                         fprintf(stderr, "Debug: ");
103                         vfprintf(stderr, format, ap);
104                         fflush(stderr);
105                 }
106 #ifndef __GNUC__
107                 /* let's be portable */
108                 va_end(ap);
109                 va_start(ap, format);
110 #endif
111                 vputlog(LOG_DEBUG, "Debug", format, ap);
112         }
113         va_end(ap);
114 }
115 #endif
116
117 void    message(const char *format, ...)
118 {
119         va_list ap;
120         
121         va_start(ap, format);
122         if(_mdvi_log_level >= LOG_INFO) {
123                 fprintf(stderr, "%s: ", program_name);
124                 vfprintf(stderr, format, ap);
125 #ifndef __GNUC__
126                 va_end(ap);
127                 va_start(ap, format);
128 #endif
129         }
130         vputlog(LOG_INFO, NULL, format, ap);
131         va_end(ap);
132 }
133
134 void    crash(const char *format, ...)
135 {
136         va_list ap;
137         
138         va_start(ap, format);
139         fprintf(stderr, "%s: %s: ", 
140                 program_name, 
141                 gettext(messages[(int)time(NULL) % NMSGS]));
142         vfprintf(stderr, format, ap);
143 #ifndef __GNUC__
144         /* let's be portable */
145         va_end(ap);
146         va_start(ap, format);
147 #endif
148         vputlog(LOG_ERROR, _("Crashing"), format, ap);
149         va_end(ap);
150         abort();
151 }
152
153 void    error(const char *format, ...)
154 {
155         va_list ap;
156         
157         va_start(ap, format);
158         fprintf(stderr, _("%s: Error: "), program_name);
159         vfprintf(stderr, format, ap);
160 #ifndef __GNUC__
161         /* let's be portable */
162         va_end(ap);
163         va_start(ap, format);
164 #endif
165         vputlog(LOG_ERROR, _("Error"), format, ap);
166         va_end(ap);
167 }
168
169 void    warning(const char *format, ...)
170 {
171         va_list ap;
172         
173         va_start(ap, format);
174         fprintf(stderr, _("%s: Warning: "), program_name);
175         vfprintf(stderr, format, ap);
176 #ifndef __GNUC__
177         /* let's be portable */
178         va_end(ap);
179         va_start(ap, format);
180 #endif
181         vputlog(LOG_WARN, _("Warning"), format, ap);
182         va_end(ap);
183 }
184
185 void    fatal(const char *format, ...)
186 {
187         va_list ap;
188         
189         va_start(ap, format);
190         fprintf(stderr, _("%s: Fatal: "), program_name);
191         vfprintf(stderr, format, ap);
192 #ifndef __GNUC__
193         /* let's be portable */
194         va_end(ap);
195         va_start(ap, format);
196 #endif
197         vputlog(LOG_ERROR, _("Fatal"), format, ap);
198         va_end(ap);
199 #ifndef NODEBUG
200         abort();
201 #else
202         exit(EXIT_FAILURE);
203 #endif
204 }
205
206 void    *mdvi_malloc(size_t nelems)
207 {
208         void    *ptr = malloc(nelems);
209         
210         if(ptr == NULL)
211                 fatal(_("out of memory allocating %u bytes\n"),
212                         (unsigned)nelems);
213         return ptr;
214 }
215
216 void    *mdvi_realloc(void *data, size_t newsize)
217 {
218         void    *ptr;
219         
220         if(newsize == 0)
221                 crash(_("attempted to reallocate with zero size\n"));
222         ptr = realloc(data, newsize);
223         if(ptr == NULL)
224                 fatal(_("failed to reallocate %u bytes\n"), (unsigned)newsize);
225         return ptr;     
226 }
227
228 void    *mdvi_calloc(size_t nmemb, size_t size)
229 {
230         void    *ptr;
231         
232         if(nmemb == 0)
233                 crash(_("attempted to callocate 0 members\n"));
234         if(size == 0)
235                 crash(_("attempted to callocate %u members with size 0\n"),
236                         (unsigned)nmemb);
237         ptr = calloc(nmemb, size);
238         if(ptr == 0)
239                 fatal(_("failed to allocate %ux%u bytes\n"),
240                         (unsigned)nmemb, (unsigned)size);
241         return ptr;
242 }
243
244 void    mdvi_free(void *ptr)
245 {
246         if(ptr == NULL)
247                 crash(_("attempted to free NULL pointer\n"));
248         free(ptr);
249 }
250
251 char    *mdvi_strdup(const char *string)
252 {
253         int     length;
254         char    *ptr;
255         
256         length = strlen(string) + 1;
257         ptr = (char *)mdvi_malloc(length);
258         memcpy(ptr, string, length);
259         return ptr;
260 }
261
262 /* `to' should have room for length+1 bytes */
263 char    *mdvi_strncpy(char *to, const char *from, size_t length)
264 {
265         strncpy(to, from, length);
266         to[length] = '\0';
267         return to;
268 }
269
270 char    *mdvi_strndup(const char *string, size_t length)
271 {
272         int     n;
273         char    *ptr;
274         
275         n = strlen(string);
276         if(n > length)
277                 n = length;
278         ptr = (char *)mdvi_malloc(n + 1);
279         memcpy(ptr, string, n);
280         return ptr;
281 }
282
283 void    *mdvi_memdup(const void *data, size_t length)
284 {
285         void    *ptr = mdvi_malloc(length);
286         
287         memcpy(ptr, data, length);
288         return ptr;
289 }
290
291 char   *mdvi_strrstr (const char *haystack, const char *needle)
292 {
293         size_t i;
294         size_t needle_len;
295         size_t haystack_len;
296         const char *p;
297
298         needle_len = strlen (needle);
299         haystack_len = strlen (haystack);
300
301         if (needle_len == 0)
302                 return NULL;
303
304         if (haystack_len < needle_len)
305                 return (char *)haystack;
306
307         p = haystack + haystack_len - needle_len;
308         while (p >= haystack) {
309                 for (i = 0; i < needle_len; i++)
310                         if (p[i] != needle[i])
311                                 goto next;
312
313                 return (char *)p;
314
315         next:
316                 p--;
317         }
318
319         return NULL;
320 }
321
322 char   *mdvi_build_path_from_cwd (const char *path)
323 {
324         char  *ptr;
325         char  *buf = NULL;
326         size_t buf_size = 512;
327
328         while (1) {
329                 buf = mdvi_realloc (buf, buf_size);
330                 if ((ptr = getcwd (buf, buf_size)) == NULL && errno == ERANGE) {
331                         buf_size *= 2;
332                 } else {
333                         buf = ptr;
334                         break;
335                 }
336         }
337
338         buf = mdvi_realloc (buf, strlen (buf) + strlen (path) + 2);
339         strcat (buf, "/");
340         strncat (buf, path, strlen (path));
341         
342         return buf;
343 }
344
345 double  unit2pix_factor(const char *spec)
346 {
347         double  val;
348         double  factor;
349         const char *p, *q;
350         static const char *units = "incmmmmtptpcddccspbpftydcs";
351         
352         val = 0.0;
353         
354         for(p = spec; *p >= '0' && *p <= '9'; p++)
355                 val = 10.0 * val + (double)(*p - '0');
356         if(*p == '.') {
357                 p++;
358                 factor = 0.1;
359                 while(*p && *p >= '0' && *p <= '9') {
360                         val += (*p++ - '0') * factor;
361                         factor = factor * 0.1;
362                 }
363         }
364         factor = 1.0;
365         for(q = units; *q; q += 2) {
366                 if(p[0] == q[0] && p[1] == q[1])
367                         break;
368         }
369         switch((int)(q - units)) {
370         /*in*/  case 0:  factor = 1.0; break;
371         /*cm*/  case 2:  factor = 1.0 / 2.54; break;
372         /*mm*/  case 4:  factor = 1.0 / 25.4; break;
373         /*mt*/  case 6:  factor = 1.0 / 0.0254; break;
374         /*pt*/  case 8:  factor = 1.0 / 72.27; break;
375         /*pc*/  case 10: factor = 12.0 / 72.27; break;
376         /*dd*/  case 12: factor = (1238.0 / 1157.0) / 72.27; break;
377         /*cc*/  case 14: factor = 12 * (1238.0 / 1157.0) / 72.27; break;
378         /*sp*/  case 16: factor = 1.0 / (72.27 * 65536); break;
379         /*bp*/  case 18: factor = 1.0 / 72.0; break;
380         /*ft*/  case 20: factor = 12.0; break;
381         /*yd*/  case 22: factor = 36.0; break;
382         /*cs*/  case 24: factor = 1.0 / 72000.0; break;
383                 default: factor = 1.0;
384         }
385         return factor * val;
386 }
387
388 int     unit2pix(int dpi, const char *spec)
389 {
390         double  factor = unit2pix_factor(spec);
391         
392         return (int)(factor * dpi + 0.5);
393 }
394
395 Ulong   get_mtime(int fd)
396 {
397         struct stat st;
398         
399         if(fstat(fd, &st) == 0)
400                 return (Ulong)st.st_mtime;
401         return 0;
402 }
403
404 char    *xstradd(char *dest, size_t *size, size_t n, const char *src, size_t m)
405 {
406         if(m == 0)
407                 m = strlen(src);
408         if(n + m >= *size) {
409                 dest = mdvi_realloc(dest, n + m + 1);
410                 *size = n + m + 1;
411         }
412         memcpy(dest + n, src, m);
413         dest[n + m] = 0;
414         return dest;
415 }
416
417 char    *getword(char *string, const char *delim, char **end)
418 {
419         char *ptr;
420         char *word;
421         
422         /* skip leading delimiters */
423         for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
424
425         if(*ptr == 0)
426                 return NULL;
427         word = ptr++;
428         /* skip non-delimiters */
429         while(*ptr && !strchr(delim, *ptr))
430                 ptr++;
431         *end = (char *)ptr;
432         return word;
433 }
434
435 char    *getstring(char *string, const char *delim, char **end)
436 {
437         char *ptr;
438         char *word;
439         int     quoted = 0;
440         
441         /* skip leading delimiters */
442         for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
443         
444         if(ptr == NULL)
445                 return NULL;
446         quoted = (*ptr == '"');
447         if(quoted)
448                 for(word = ++ptr; *ptr && *ptr != '"'; ptr++);
449         else
450                 for(word = ptr; *ptr && !strchr(delim, *ptr); ptr++);
451         *end = (char *)ptr;
452         return word;
453 }
454
455 static long pow2(size_t n)
456 {
457         long    x = 8; /* don't bother allocating less than this */
458         
459         while(x < n)
460                 x <<= 1L;
461         return x;
462 }
463
464 void    dstring_init(Dstring *dstr)
465 {
466         dstr->data = NULL;
467         dstr->size = 0;
468         dstr->length = 0;
469 }
470
471 int     dstring_append(Dstring *dstr, const char *string, int len)
472 {
473         if(len < 0)
474                 len = strlen(string);
475         if(len) {
476                 if(dstr->length + len >= dstr->size) {
477                         dstr->size = pow2(dstr->length + len + 1);
478                         dstr->data = mdvi_realloc(dstr->data, dstr->size);
479                 }
480                 memcpy(dstr->data + dstr->length, string, len);
481                 dstr->length += len;
482                 dstr->data[dstr->length] = 0;
483         } else if(dstr->size == 0) {
484                 ASSERT(dstr->data == NULL);
485                 dstr->size = 8;
486                 dstr->data = mdvi_malloc(8);
487                 dstr->data[0] = 0;
488         }
489                 
490         return dstr->length;
491 }
492
493 int     dstring_copy(Dstring *dstr, int pos, const char *string, int len)
494 {
495         ASSERT(pos >= 0);
496         if(len < 0)
497                 len = strlen(string);
498         if(len) {
499                 if(pos + len >= dstr->length) {
500                         dstr->length = pos;
501                         return dstring_append(dstr, string, len);
502                 }
503                 memcpy(dstr->data + pos, string, len);
504         }
505         return dstr->length;
506 }
507
508 int     dstring_insert(Dstring *dstr, int pos, const char *string, int len)
509 {
510         ASSERT(pos >= 0);
511         if(pos == dstr->length)
512                 return dstring_append(dstr, string, len);
513         if(len < 0)
514                 len = strlen(string);
515         if(len) {
516                 if(dstr->length + len >= dstr->size) {
517                         dstr->size = pow2(dstr->length + len + 1);
518                         dstr->data = mdvi_realloc(dstr->data, dstr->size);
519                 }
520                 /* make room */
521                 memmove(dstr->data + pos, dstr->data + pos + len, len);
522                 /* now copy */
523                 memcpy(dstr->data + pos, string, len);
524                 dstr->length += len;
525                 dstr->data[dstr->length] = 0;
526         }
527         return dstr->length;
528 }
529
530 int     dstring_new(Dstring *dstr, const char *string, int len)
531 {
532         if(len < 0)
533                 len = strlen(string);
534         if(len) {
535                 dstr->size = pow2(len + 1);
536                 dstr->data = mdvi_malloc(dstr->size * len);
537                 memcpy(dstr->data, string, len);
538         } else
539                 dstring_init(dstr);
540         return dstr->length;
541 }
542
543 void    dstring_reset(Dstring *dstr)
544 {
545         if(dstr->data)
546                 mdvi_free(dstr->data);
547         dstring_init(dstr);
548 }
549