source: util.c @ dad943e

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