source: util.c @ 995eb4b

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 995eb4b was e3d9c77, checked in by James M. Kretchmar <kretch@mit.edu>, 20 years ago
Write owl_text_quote Moved some functions between util.c, text.c and zephyr.c
  • Property mode set to 100644
File size: 15.9 KB
Line 
1#include "owl.h"
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <ctype.h>
6
7static const char fileIdent[] = "$Id$";
8
9void sepbar(char *in)
10{
11  char buff[1024];
12  WINDOW *sepwin;
13  owl_messagelist *ml;
14  owl_view *v;
15  int x, y, i;
16  char *foo, *appendtosepbar;
17
18  sepwin=owl_global_get_curs_sepwin(&g);
19  ml=owl_global_get_msglist(&g);
20  v=owl_global_get_current_view(&g);
21
22  werase(sepwin);
23  wattron(sepwin, A_REVERSE);
24  if (owl_global_is_fancylines(&g)) {
25    whline(sepwin, ACS_HLINE, owl_global_get_cols(&g));
26  } else {
27    whline(sepwin, '-', owl_global_get_cols(&g));
28  }
29
30  if (owl_global_is_sepbar_disable(&g)) {
31    getyx(sepwin, y, x);
32    wmove(sepwin, y, owl_global_get_cols(&g)-1);
33    return;
34  }
35
36  wmove(sepwin, 0, 2); 
37
38  if (owl_messagelist_get_size(ml)==0) {
39    strcpy(buff, " (-/-) ");
40  } else {
41    snprintf(buff, 1024, " (%i/%i/%i) ", owl_global_get_curmsg(&g)+1,
42            owl_view_get_size(v),
43            owl_messagelist_get_size(ml));
44  }
45  waddstr(sepwin, buff);
46
47  foo=owl_view_get_filtname(v);
48  if (strcmp(foo, "all")) wattroff(sepwin, A_REVERSE);
49  waddstr(sepwin, " ");
50  waddstr(sepwin, owl_view_get_filtname(v));
51  waddstr(sepwin, " ");
52  if (strcmp(foo, "all")) wattron(sepwin, A_REVERSE);
53
54  if (owl_mainwin_is_curmsg_truncated(owl_global_get_mainwin(&g))) {
55    getyx(sepwin, y, x);
56    wmove(sepwin, y, x+2);
57    wattron(sepwin, A_BOLD);
58    waddstr(sepwin, " <truncated> ");
59    wattroff(sepwin, A_BOLD);
60  }
61
62  i=owl_mainwin_get_last_msg(owl_global_get_mainwin(&g));
63  if ((i != -1) &&
64      (i < owl_view_get_size(v)-1)) {
65    getyx(sepwin, y, x);
66    wmove(sepwin, y, x+2);
67    wattron(sepwin, A_BOLD);
68    waddstr(sepwin, " <more> ");
69    wattroff(sepwin, A_BOLD);
70  }
71
72  if (owl_global_get_rightshift(&g)>0) {
73    getyx(sepwin, y, x);
74    wmove(sepwin, y, x+2);
75    snprintf(buff, 1024, " right: %i ", owl_global_get_rightshift(&g));
76    waddstr(sepwin, buff);
77  }
78
79  if (owl_global_is_zaway(&g)) {
80    getyx(sepwin, y, x);
81    wmove(sepwin, y, x+2);
82    wattron(sepwin, A_BOLD);
83    wattroff(sepwin, A_REVERSE);
84    waddstr(sepwin, " ZAWAY ");
85    wattron(sepwin, A_REVERSE);
86    wattroff(sepwin, A_BOLD);
87  }
88
89  if (owl_global_get_curmsg_vert_offset(&g)) {
90    getyx(sepwin, y, x);
91    wmove(sepwin, y, x+2);
92    wattron(sepwin, A_BOLD);
93    wattroff(sepwin, A_REVERSE);
94    waddstr(sepwin, " SCROLL ");
95    wattron(sepwin, A_REVERSE);
96    wattroff(sepwin, A_BOLD);
97  }
98 
99  if (in) {
100    getyx(sepwin, y, x);
101    wmove(sepwin, y, x+2);
102    waddstr(sepwin, in);
103  }
104
105  appendtosepbar = owl_global_get_appendtosepbar(&g);
106  if (appendtosepbar && *appendtosepbar) {
107    getyx(sepwin, y, x);
108    wmove(sepwin, y, x+2);
109    waddstr(sepwin, " ");
110    waddstr(sepwin, owl_global_get_appendtosepbar(&g));
111    waddstr(sepwin, " ");
112  }
113
114  getyx(sepwin, y, x);
115  wmove(sepwin, y, owl_global_get_cols(&g)-1);
116   
117  wattroff(sepwin, A_BOLD);
118  wattroff(sepwin, A_REVERSE);
119  wnoutrefresh(sepwin);
120}
121
122
123void pophandler_quit(int ch)
124{
125  if (ch=='q') {
126    owl_popwin_close(owl_global_get_popwin(&g));
127  }
128}
129
130char **atokenize(char *buffer, char *sep, int *i)
131{
132  /* each element of return must be freed by user */
133  char **args;
134  char *workbuff, *foo;
135  int done=0, first=1, count=0;
136
137  workbuff=owl_malloc(strlen(buffer)+1);
138  memcpy(workbuff, buffer, strlen(buffer)+1);
139
140  args=NULL;
141  while (!done) {
142    if (first) {
143      first=0;
144      foo=(char *)strtok(workbuff, sep);
145    } else {
146      foo=(char *)strtok(NULL, sep);
147    }
148    if (foo==NULL) {
149      done=1;
150    } else {
151      args=(char **)owl_realloc(args, sizeof(char *) * (count+1));
152      args[count]=owl_malloc(strlen(foo)+1);
153      strcpy(args[count], foo);
154      count++;
155    }
156  }
157  *i=count;
158  owl_free(workbuff);
159  return(args);
160}
161
162char *skiptokens(char *buff, int n) {
163  /* skips n tokens and returns where that would be.
164   * TODO: handle quotes more sanely. */
165 
166  int inquotes=0;
167  while (*buff && n>0) {
168      while (*buff == ' ') buff++;
169      while (*buff && (inquotes || *buff != ' ')) { 
170        if (*buff == '"' || *buff == '\'') inquotes=!inquotes;
171        buff++;
172      }
173      while (*buff == ' ') buff++;
174      n--;
175  }
176  return buff;
177}
178
179void atokenize_free(char **tok, int nels)
180{
181  int i;
182  for (i=0; i<nels; i++) {
183    owl_free(tok[i]);
184  }
185  owl_free(tok);
186}
187
188
189void owl_parsefree(char **argv, int argc)
190{
191  int i;
192
193  if (!argv) return;
194 
195  for (i=0; i<argc; i++) {
196    if (argv[i]) owl_free(argv[i]);
197  }
198  owl_free(argv);
199}
200
201char **owl_parseline(char *line, int *argc)
202{
203  /* break a command line up into argv, argc.  The caller must free
204     the returned values.  If there is an error argc will be set to
205     -1, argv will be NULL and the caller does not need to free
206     anything */
207
208  char **argv;
209  int i, len, between=1;
210  char *curarg;
211  char quote;
212
213  argv=owl_malloc(sizeof(char *));
214  len=strlen(line);
215  curarg=owl_malloc(len+10);
216  strcpy(curarg, "");
217  quote='\0';
218  *argc=0;
219  for (i=0; i<len+1; i++) {
220    /* find the first real character */
221    if (between) {
222      if (line[i]==' ' || line[i]=='\t' || line[i]=='\0') {
223        continue;
224      } else {
225        between=0;
226        i--;
227        continue;
228      }
229    }
230
231    /* deal with a quote character */
232    if (line[i]=='"' || line[i]=="'"[0]) {
233      /* if this type of quote is open, close it */
234      if (quote==line[i]) {
235        quote='\0';
236        continue;
237      }
238
239      /* if no quoting is open then open with this */
240      if (quote=='\0') {
241        quote=line[i];
242        continue;
243      }
244
245      /* if another type of quote is open then treat this as a literal */
246      curarg[strlen(curarg)+1]='\0';
247      curarg[strlen(curarg)]=line[i];
248      continue;
249    }
250
251    /* if it's not a space or end of command, then use it */
252    if (line[i]!=' ' && line[i]!='\t' && line[i]!='\n' && line[i]!='\0') {
253      curarg[strlen(curarg)+1]='\0';
254      curarg[strlen(curarg)]=line[i];
255      continue;
256    }
257
258    /* otherwise, if we're not in quotes, add the whole argument */
259    if (quote=='\0') {
260      /* add the argument */
261      argv=owl_realloc(argv, sizeof(char *)*((*argc)+1));
262      argv[*argc]=owl_malloc(strlen(curarg)+2);
263      strcpy(argv[*argc], curarg);
264      *argc=*argc+1;
265      strcpy(curarg, "");
266      between=1;
267      continue;
268    }
269
270    /* if it is a space and we're in quotes, then use it */
271    curarg[strlen(curarg)+1]='\0';
272    curarg[strlen(curarg)]=line[i];
273  }
274
275  /* check for unbalanced quotes */
276  if (quote!='\0') {
277    owl_parsefree(argv, *argc);
278    *argc=-1;
279    return(NULL);
280  }
281
282  return(argv);
283}
284
285/* caller must free the return */
286char *owl_util_minutes_to_timestr(int in)
287{
288  int days, hours;
289  long run;
290  char *out;
291
292  run=in;
293
294  days=run/1440;
295  run-=days*1440;
296  hours=run/60;
297  run-=hours*60;
298
299  if (days>0) {
300    out=owl_sprintf("%i d %2.2i:%2.2i", days, hours, run);
301  } else {
302    out=owl_sprintf("    %2.2i:%2.2i", hours, run);
303  }
304  return(out);
305}
306
307/* return the index of the last char before a change from the first one */
308int owl_util_find_trans(char *in, int len)
309{
310  int i;
311  for (i=1; i<len; i++) {
312    if (in[i] != in[0]) return(i-1);
313  }
314  return(i);
315}
316
317/* downcase the string 'foo' */
318void downstr(char *foo)
319{
320  int i;
321  for (i=0; foo[i]!='\0'; i++) {
322    foo[i]=tolower(foo[i]);
323  }
324}
325
326/* Caller must free response.
327 * Takes in strings which are space-separated lists of tokens
328 * and returns a single string containing no token more than once.
329 * If prohibit is non-null, no token may start with a character
330 * in prohibit.
331 */
332char *owl_util_uniq(char *A, char *B, char *prohibit)
333{
334 
335  char *cat, **tok;
336  int toklen, i, j, first=1;
337  cat = owl_malloc(strlen(A)+strlen(B)+3);
338  strcpy(cat, A);
339  strcat(cat, " ");
340  strcat(cat, B);
341  tok = atokenize(cat, " ", &toklen);
342  strcpy(cat, "");
343  for (i=0; i<toklen; i++) {
344    int dup=0;
345    for (j=0; j<i; j++) {
346      if (!strcmp(tok[i], tok[j])) dup=1;
347    }
348    if (!dup && (!prohibit || !strchr(prohibit, tok[i][0]))) {
349      if (!first) {
350        strcat(cat, " ");
351      }
352      first=0;
353      strcat(cat, tok[i]);
354    }
355  }
356  atokenize_free(tok, toklen);
357  return(cat);
358}
359
360/* hooks for doing memory allocation et. al. in owl */
361
362void *owl_malloc(size_t size)
363{
364  return(malloc(size));
365}
366
367void owl_free(void *ptr)
368{
369  free(ptr);
370}
371
372char *owl_strdup(const char *s1)
373{
374  return(strdup(s1));
375}
376
377void *owl_realloc(void *ptr, size_t size)
378{
379  return(realloc(ptr, size));
380}
381
382/* allocates memory and returns the string or null.
383 * caller must free the string.
384 * from Linux sprintf man page.
385 */
386char *owl_sprintf(const char *fmt, ...)
387{
388  int n, size = 100;
389  char *p;
390  va_list ap;
391  if ((p = owl_malloc (size)) == NULL) return (NULL);
392  while (1) {
393    /* Try to print in the allocated space. */
394    va_start(ap, fmt);
395    n = vsnprintf (p, size, fmt, ap);
396    va_end(ap);
397    /* If that worked, return the string. */
398    if (n > -1 && n < size)
399      return p;
400    /* Else try again with more space. */
401    if (n > -1)    /* glibc 2.1 */
402      size = n+1; /* precisely what is needed */
403    else           /* glibc 2.0 */
404      size *= 2;  /* twice the old size */
405    if ((p = owl_realloc (p, size)) == NULL)
406      return NULL;
407  }
408}
409
410/* Return the owl color associated with the named color */
411int owl_util_string_to_color(char *color)
412{
413  if (!strcasecmp(color, "black")) {
414    return(OWL_COLOR_BLACK);
415  } else if (!strcasecmp(color, "red")) {
416    return(OWL_COLOR_RED);
417  } else if (!strcasecmp(color, "green")) {
418    return(OWL_COLOR_GREEN);
419  } else if (!strcasecmp(color, "yellow")) {
420    return(OWL_COLOR_YELLOW);
421  } else if (!strcasecmp(color, "blue")) {
422    return(OWL_COLOR_BLUE);
423  } else if (!strcasecmp(color, "magenta")) {
424    return(OWL_COLOR_MAGENTA);
425  } else if (!strcasecmp(color, "cyan")) {
426    return(OWL_COLOR_CYAN);
427  } else if (!strcasecmp(color, "white")) {
428    return(OWL_COLOR_WHITE);
429  } else if (!strcasecmp(color, "default")) {
430    return(OWL_COLOR_DEFAULT);
431  }
432  return(OWL_COLOR_DEFAULT);
433}
434
435/* Return a string name of the given owl color */
436char *owl_util_color_to_string(int color)
437{
438  if (color==OWL_COLOR_BLACK)   return("black");
439  if (color==OWL_COLOR_RED)     return("red");
440  if (color==OWL_COLOR_GREEN)   return("green");
441  if (color==OWL_COLOR_YELLOW)  return("yellow");
442  if (color==OWL_COLOR_BLUE)    return("blue");
443  if (color==OWL_COLOR_MAGENTA) return("magenta");
444  if (color==OWL_COLOR_CYAN)    return("cyan");
445  if (color==OWL_COLOR_WHITE)   return("white");
446  if (color==OWL_COLOR_DEFAULT) return("default");
447  return("Unknown color");
448}
449
450/* Get the default tty name.  Caller must free the return */
451char *owl_util_get_default_tty()
452{
453  char *out, *tmp;
454
455  if (getenv("DISPLAY")) {
456    out=owl_strdup(getenv("DISPLAY"));
457  } else if ((tmp=ttyname(fileno(stdout)))!=NULL) {
458    out=owl_strdup(tmp);
459    if (!strncmp(out, "/dev/", 5)) {
460      owl_free(out);
461      out=owl_strdup(tmp+5);
462    }
463  } else {
464    out=owl_strdup("unknown");
465  }
466  return(out);
467}
468
469
470/* Animation hack */
471void owl_hack_animate()
472{
473  owl_messagelist *ml;
474  owl_message *m;
475  owl_fmtext *fm;
476  char *text, *ptr;
477  int place;
478
479  /* grab the first message and make sure its id is 0 */
480  ml=owl_global_get_msglist(&g);
481  m=owl_messagelist_get_element(ml, 0);
482  if (!m) return;
483  if (owl_message_get_id(m)!=0) return;
484
485  fm=owl_message_get_fmtext(m);
486  text=owl_fmtext_get_text(fm);
487
488  ptr=strstr(text, "OvO");
489  if (ptr) {
490    place=ptr-text;
491    owl_fmtext_set_char(fm, place, '-');
492    owl_fmtext_set_char(fm, place+2, '-');
493
494    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
495    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
496      owl_popwin_refresh(owl_global_get_popwin(&g));
497      /* TODO: this is a broken kludge */
498      if (owl_global_get_viewwin(&g)) {
499        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
500      }
501    }
502    owl_global_set_needrefresh(&g);
503    return;
504  }
505
506  ptr=strstr(text, "-v-");
507  if (ptr) {
508    place=ptr-text;
509    owl_fmtext_set_char(fm, place, 'O');
510    owl_fmtext_set_char(fm, place+2, 'O');
511
512    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
513    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
514      owl_popwin_refresh(owl_global_get_popwin(&g));
515      /* TODO: this is a broken kludge */
516      if (owl_global_get_viewwin(&g)) {
517        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
518      }
519    }
520    owl_global_set_needrefresh(&g);
521    return;
522  }
523}
524
525/* strip leading and trailing new lines.  Caller must free the
526 * return.
527 */
528char *owl_util_stripnewlines(char *in)
529{
530 
531  char  *tmp, *ptr1, *ptr2, *out;
532
533  ptr1=tmp=owl_strdup(in);
534  while (ptr1[0]=='\n') {
535    ptr1++;
536  }
537  ptr2=ptr1+strlen(ptr1)-1;
538  while (ptr2[0]=='\n' && ptr2>ptr1) {
539    ptr2[0]='\0';
540    ptr2--;
541  }
542
543  out=owl_strdup(ptr1);
544  owl_free(tmp);
545  return(out);
546}
547
548/* Delete the line matching "line" from the named file.  If no such
549 * line is found the file is left intact.  If backup==1 then create a
550 * backupfile containing the original contents.  This is an
551 * inefficient impelementation which reads the entire file into
552 * memory.
553 */
554void owl_util_file_deleteline(char *filename, char *line, int backup)
555{
556  char buff[LINE], *text;
557  char *backupfilename="";
558  FILE *file, *backupfile=NULL;
559  int size, newline;
560
561  /* open the file for reading */
562  file=fopen(filename, "r");
563  if (!file) {
564    owl_function_error("Error opening file %s", filename);
565    return;
566  }
567
568  /* open the backup file for writing */
569  if (backup) {
570    backupfilename=owl_sprintf("%s.backup", filename);
571    backupfile=fopen(backupfilename, "w");
572    if (!backupfile) {
573      owl_function_error("Error opening file %s for writing", backupfilename);
574      owl_free(backupfilename);
575      return;
576    }
577    owl_free(backupfilename);
578  }
579
580  /* we'll read the entire file into memory, minus the line we don't want and
581   * and at the same time create the backup file if necessary
582   */
583  text=owl_malloc(LINE);
584  strcpy(text, "");
585  size=LINE;
586  while (fgets(buff, LINE, file)!=NULL) {
587    /* strip the newline */
588    newline=0;
589    if (buff[strlen(buff)-1]=='\n') {
590      buff[strlen(buff)-1]='\0';
591      newline=1;
592    }
593   
594    /* if we don't match the line, add to saved text in memory */
595    if (strcasecmp(buff, line)) {
596      size+=LINE;
597      text=owl_realloc(text, size);
598      strcat(text, buff);
599      if (newline) strcat(text, "\n");
600    }
601
602    /* write to backupfile if necessary */
603    if (backup) {
604      fputs(buff, backupfile);
605      if (newline) fputs("\n", backupfile);
606    }
607  }
608  if (backup) fclose(backupfile);
609  fclose(file);
610
611  /* now rewrite the original file from memory */
612  file=fopen(filename, "w");
613  if (!file) {
614    owl_function_error("WARNING: Error opening %s for writing.  Use %s to restore.", filename, backupfilename);
615    owl_function_beep();
616    owl_free(line);
617    return;
618  }
619
620  fputs(text, file);
621  fclose(file);
622}
623
624/**************************************************************************/
625/************************* REGRESSION TESTS *******************************/
626/**************************************************************************/
627
628#ifdef OWL_INCLUDE_REG_TESTS
629
630#define FAIL_UNLESS(desc,pred) printf("\t%-4s: %s\n", (pred)?"ok":(numfailed++,"FAIL"), desc)
631
632int owl_util_regtest(void)
633{
634  int numfailed=0;
635
636  printf("BEGIN testing owl_util\n");
637
638  FAIL_UNLESS("owl_util_substitute 1",
639              !strcmp("foo", owl_text_substitute("foo", "", "Y")));
640  FAIL_UNLESS("owl_text_substitute 2",
641              !strcmp("fYZYZ", owl_text_substitute("foo", "o", "YZ")));
642  FAIL_UNLESS("owl_text_substitute 3",
643              !strcmp("foo", owl_text_substitute("fYZYZ", "YZ", "o")));
644  FAIL_UNLESS("owl_text_substitute 4",
645              !strcmp("/u/foo/meep", owl_text_substitute("~/meep", "~", "/u/foo")));
646
647  FAIL_UNLESS("skiptokens 1", 
648              !strcmp("bar quux", skiptokens("foo bar quux", 1)));
649  FAIL_UNLESS("skiptokens 2", 
650              !strcmp("meep", skiptokens("foo 'bar quux' meep", 2)));
651
652  FAIL_UNLESS("owl_util_uniq 1", 
653              !strcmp("foo bar x", owl_util_uniq("foo", "bar x", "-")));
654  FAIL_UNLESS("owl_util_uniq 2", 
655              !strcmp("foo bar x", owl_util_uniq("foo", "bar -y x", "-")));
656  FAIL_UNLESS("owl_util_uniq 3", 
657              !strcmp("meep foo bar", owl_util_uniq("meep foo", "bar foo meep", "-")));
658
659  if (numfailed) printf("*** WARNING: failures encountered with owl_util\n");
660  printf("END testing owl_util (%d failures)\n", numfailed);
661  return(numfailed);
662}
663
664#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.