source: util.c @ af2ca19

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