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