source: util.c @ f9c43ae

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since f9c43ae was f9c43ae, checked in by James M. Kretchmar <kretch@mit.edu>, 22 years ago
Fixed up the normal scrolling code. Now it should always land on a message, but it's still not optimal. Added the variable 'smartstrip' which will strip kerberos instances out for the 'reply' command. Added -R/usr/athena/lib to the build for Athena
  • Property mode set to 100644
File size: 15.0 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
413
414char *long_zuser(char *in) {
415  char *ptr;
416
417  /* the caller must free the return */
418  if (NULL != (ptr=strchr(in, '@'))) {
419    return owl_strdup(in);
420  } else {
421    return owl_sprintf("%s@%s", in, ZGetRealm());
422  }
423}
424
425
426char *smartstripped_user(char *in) {
427  /* strip out the instance from a zsender's principal.
428   * Preserves the realm if present.
429   * the caller must free the return */
430
431  char *ptr, *realm, *out;
432
433  out=owl_strdup(in);
434
435  /* bail immeaditly if we don't have to do any work */
436  ptr=strchr(in, '.');
437  if (!strchr(in, '/') && !ptr) {
438    return(out);
439  }
440  if (ptr && strchr(in, '@') && (ptr > strchr(in, '@'))) {
441    return(out);
442  }
443
444  /* remove the realm from ptr, but hold on to it */
445  realm=strchr(out, '@');
446  if (realm) realm[0]='\0';
447
448  /* strip */
449  ptr=strchr(out, '.');
450  if (!ptr) ptr=strchr(out, '/');
451  ptr[0]='\0';
452
453  /* reattach the realm if we had one */
454  if (realm) {
455    strcat(out, "@");
456    strcat(out, realm+1);
457  }
458
459  return(out);
460}
461
462char *owl_getquoting(char *line) {
463  if (line[0]=='\0') return("'");
464  if (strchr(line, '\'')) return("\"");
465  if (strchr(line, '"')) return("'");
466  if (strchr(line, ' ')) return("'");
467  return("");
468}
469
470char *owl_util_substitute(char *in, char *from, char *to) {
471  /* Caller must free returned string.
472   * Returns a string with any occurances of 'from' replaced with 'to'.
473   * Does not currently handle backslash quoting, but may in the future.
474   */
475 
476  char *out;
477  int   outlen, tolen, fromlen, inpos=0, outpos=0;
478
479  if (!*from) return owl_strdup(in);
480
481  outlen = strlen(in)+1;
482  tolen  = strlen(to);
483  fromlen  = strlen(from);
484  out = malloc(outlen);
485
486  while (in[inpos]) {
487    if (!strncmp(in+inpos, from, fromlen)) {
488      outlen += tolen;
489      out = owl_realloc(out, outlen);
490      strcpy(out+outpos, to);
491      inpos += fromlen;
492      outpos += tolen;
493    } else {
494      out[outpos] = in[inpos];
495      inpos++; outpos++;
496    }
497  }
498  out[outpos] = '\0';
499  return(out);
500}
501
502
503int owl_util_string_to_color(char *color) {
504  if (!strcasecmp(color, "black")) {
505    return(OWL_COLOR_BLACK);
506  } else if (!strcasecmp(color, "red")) {
507    return(OWL_COLOR_RED);
508  } else if (!strcasecmp(color, "green")) {
509    return(OWL_COLOR_GREEN);
510  } else if (!strcasecmp(color, "yellow")) {
511    return(OWL_COLOR_YELLOW);
512  } else if (!strcasecmp(color, "blue")) {
513    return(OWL_COLOR_BLUE);
514  } else if (!strcasecmp(color, "magenta")) {
515    return(OWL_COLOR_MAGENTA);
516  } else if (!strcasecmp(color, "cyan")) {
517    return(OWL_COLOR_CYAN);
518  } else if (!strcasecmp(color, "white")) {
519    return(OWL_COLOR_WHITE);
520  } else if (!strcasecmp(color, "default")) {
521    return(OWL_COLOR_DEFAULT);
522  }
523  return(OWL_COLOR_DEFAULT);
524}
525
526char *owl_util_color_to_string(int color) {
527  if (color==OWL_COLOR_BLACK)   return("black");
528  if (color==OWL_COLOR_RED)     return("red");
529  if (color==OWL_COLOR_GREEN)   return("green");
530  if (color==OWL_COLOR_YELLOW)  return("yellow");
531  if (color==OWL_COLOR_BLUE)    return("blue");
532  if (color==OWL_COLOR_MAGENTA) return("magenta");
533  if (color==OWL_COLOR_CYAN)    return("cyan");
534  if (color==OWL_COLOR_WHITE)   return("white");
535  if (color==OWL_COLOR_DEFAULT) return("default");
536  return("Unknown color");
537}
538
539char *owl_util_get_default_tty() {
540  /* call must free the return */
541  char *out, *tmp;
542
543  if (getenv("DISPLAY")) {
544    out=owl_strdup(getenv("DISPLAY"));
545  } else if ((tmp=ttyname(fileno(stdout)))!=NULL) {
546    out=owl_strdup(tmp);
547    if (!strncmp(out, "/dev/", 5)) {
548      owl_free(out);
549      out=owl_strdup(tmp+5);
550    }
551  } else {
552    out=owl_strdup("unknown");
553  }
554  return(out);
555}
556
557
558void owl_hack_animate() {
559  owl_messagelist *ml;
560  owl_message *m;
561  owl_fmtext *fm;
562  char *text, *ptr;
563  int place;
564
565  /* grab the first message and make sure its id is 0 */
566  ml=owl_global_get_msglist(&g);
567  m=owl_messagelist_get_element(ml, 0);
568  if (!m) return;
569  if (owl_message_get_id(m)!=0) return;
570
571  fm=owl_message_get_fmtext(m);
572  text=owl_fmtext_get_text(fm);
573
574  ptr=strstr(text, "OvO");
575  if (ptr) {
576    place=ptr-text;
577    owl_fmtext_set_char(fm, place, '-');
578    owl_fmtext_set_char(fm, place+2, '-');
579
580    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
581    owl_global_set_needrefresh(&g);
582    return;
583  }
584
585  ptr=strstr(text, "-v-");
586  if (ptr) {
587    place=ptr-text;
588    owl_fmtext_set_char(fm, place, 'O');
589    owl_fmtext_set_char(fm, place+2, 'O');
590
591    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
592    owl_global_set_needrefresh(&g);
593    return;
594  }
595}
596
597/**************************************************************************/
598/************************* REGRESSION TESTS *******************************/
599/**************************************************************************/
600
601#ifdef OWL_INCLUDE_REG_TESTS
602
603#define FAIL_UNLESS(desc,pred) printf("\t%-4s: %s\n", (pred)?"ok":(numfailed++,"FAIL"), desc)
604
605int owl_util_regtest(void) {
606  int numfailed=0;
607
608  printf("BEGIN testing owl_util\n");
609
610  FAIL_UNLESS("owl_util_substitute 1",
611              !strcmp("foo", owl_util_substitute("foo", "", "Y")));
612  FAIL_UNLESS("owl_util_substitute 2",
613              !strcmp("fYZYZ", owl_util_substitute("foo", "o", "YZ")));
614  FAIL_UNLESS("owl_util_substitute 3",
615              !strcmp("foo", owl_util_substitute("fYZYZ", "YZ", "o")));
616  FAIL_UNLESS("owl_util_substitute 4",
617              !strcmp("/u/foo/meep", owl_util_substitute("~/meep", "~", "/u/foo")));
618
619  FAIL_UNLESS("skiptokens 1", 
620              !strcmp("bar quux", skiptokens("foo bar quux", 1)));
621  FAIL_UNLESS("skiptokens 2", 
622              !strcmp("meep", skiptokens("foo 'bar quux' meep", 2)));
623
624  FAIL_UNLESS("owl_util_uniq 1", 
625              !strcmp("foo bar x", owl_util_uniq("foo", "bar x", "-")));
626  FAIL_UNLESS("owl_util_uniq 2", 
627              !strcmp("foo bar x", owl_util_uniq("foo", "bar -y x", "-")));
628  FAIL_UNLESS("owl_util_uniq 3", 
629              !strcmp("meep foo bar", owl_util_uniq("meep foo", "bar foo meep", "-")));
630
631  if (numfailed) printf("*** WARNING: failures encountered with owl_util\n");
632  printf("END testing owl_util (%d failures)\n", numfailed);
633  return(numfailed);
634}
635
636#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.