source: functions.c @ 59cf91c

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 59cf91c was 59cf91c, checked in by Erik Nygren <nygren@mit.edu>, 18 years ago
Attempts to stay near the current message when switching views. When switching from an empty view to one we've previously been in, the new current message position will attempt to be close to the current position from the last time we visited that view.
  • Property mode set to 100644
File size: 60.6 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <signal.h>
5#include <string.h>
6#include <com_err.h>
7#include <time.h>
8#include "owl.h"
9
10static const char fileIdent[] = "$Id$";
11
12void owl_function_noop(void) {
13  return;
14}
15
16char *owl_function_command(char *cmdbuff) {
17  owl_function_debugmsg("executing command: %s", cmdbuff);
18  return owl_cmddict_execute(owl_global_get_cmddict(&g), 
19                             owl_global_get_context(&g), cmdbuff);
20}
21
22void owl_function_command_norv(char *cmdbuff) {
23  char *rv;
24  rv = owl_function_command(cmdbuff);
25  if (rv) owl_free(rv);
26}
27
28void owl_function_command_alias(char *alias_from, char *alias_to) {
29  owl_cmddict_add_alias(owl_global_get_cmddict(&g), alias_from, alias_to);
30}
31
32owl_cmd *owl_function_get_cmd(char *name) {
33  return owl_cmddict_find(owl_global_get_cmddict(&g), name);
34}
35
36void owl_function_show_commands() {
37  owl_list l;
38  owl_fmtext fm;
39
40  owl_fmtext_init_null(&fm);
41  owl_fmtext_append_bold(&fm, "Commands:  ");
42  owl_fmtext_append_normal(&fm, "(use 'show command <name>' for details)\n");
43  owl_cmddict_get_names(owl_global_get_cmddict(&g), &l);
44  owl_fmtext_append_list(&fm, &l, "\n", owl_function_cmd_describe);
45  owl_fmtext_append_normal(&fm, "\n");
46  owl_function_popless_fmtext(&fm);
47  owl_cmddict_namelist_free(&l);
48  owl_fmtext_free(&fm);
49}
50
51char *owl_function_cmd_describe(void *name) {
52  owl_cmd *cmd = owl_cmddict_find(owl_global_get_cmddict(&g), name);
53  if (cmd) return owl_cmd_describe(cmd);
54  else return(NULL);
55}
56
57void owl_function_show_command(char *name) {
58  owl_function_help_for_command(name);
59}
60
61void owl_function_adminmsg(char *header, char *body) {
62  owl_message *m;
63  int followlast;
64
65  followlast=owl_global_should_followlast(&g);
66  m=owl_malloc(sizeof(owl_message));
67  owl_message_create_admin(m, header, body);
68  owl_messagelist_append_element(owl_global_get_msglist(&g), m);
69  owl_view_consider_message(owl_global_get_current_view(&g), m);
70
71  if (followlast) owl_function_lastmsg_noredisplay();
72
73  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
74  if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
75    owl_popwin_refresh(owl_global_get_popwin(&g));
76  }
77 
78  wnoutrefresh(owl_global_get_curs_recwin(&g));
79  owl_global_set_needrefresh(&g);
80}
81
82void owl_function_adminmsg_outgoing(char *header, char *body, char *zwriteline) {
83  owl_message *m;
84  int followlast;
85 
86  followlast=owl_global_should_followlast(&g);
87  m=owl_malloc(sizeof(owl_message));
88  owl_message_create_admin(m, header, body);
89  owl_message_set_admin_outgoing(m, zwriteline);
90  owl_messagelist_append_element(owl_global_get_msglist(&g), m);
91  owl_view_consider_message(owl_global_get_current_view(&g), m);
92
93  if (followlast) owl_function_lastmsg_noredisplay();
94
95  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
96  if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
97    owl_popwin_refresh(owl_global_get_popwin(&g));
98  }
99 
100  wnoutrefresh(owl_global_get_curs_recwin(&g));
101  owl_global_set_needrefresh(&g);
102}
103
104void owl_function_zwrite_setup(char *line) {
105  owl_editwin *e;
106  char buff[1024];
107  owl_zwrite z;
108  int ret;
109
110  /* check the arguments */
111  ret=owl_zwrite_create_from_line(&z, line);
112  if (ret) {
113    owl_function_makemsg("Error in zwrite arugments");
114    owl_zwrite_free(&z);
115    return;
116  }
117
118  /* send a ping if necessary */
119  if (owl_global_is_txping(&g)) {
120    owl_zwrite_send_ping(&z);
121  }
122  owl_zwrite_free(&z);
123
124  /* create and setup the editwin */
125  e=owl_global_get_typwin(&g);
126  owl_editwin_new_style(e, OWL_EDITWIN_STYLE_MULTILINE,
127                        owl_global_get_msg_history(&g));
128
129  if (!owl_global_get_lockout_ctrld(&g)) {
130    owl_function_makemsg("Type your zephyr below.  End with ^D or a dot on a line by itself.  ^C will quit.");
131  } else {
132    owl_function_makemsg("Type your zephyr below.  End with a dot on a line by itself.  ^C will quit.");
133  }
134
135  owl_editwin_clear(e);
136  owl_editwin_set_dotsend(e);
137  strcpy(buff, "----> ");
138  strcat(buff, line);
139  strcat(buff, "\n");
140  owl_editwin_set_locktext(e, buff);
141
142  /* make it active */
143  owl_global_set_typwin_active(&g);
144}
145
146void owl_function_zwrite(char *line) {
147  char *tmpbuff, buff[1024];
148  owl_zwrite z;
149  int i, j;
150
151  /* create the zwrite and send the message */
152  owl_zwrite_create_from_line(&z, line);
153  owl_zwrite_send_message(&z, owl_editwin_get_text(owl_global_get_typwin(&g)));
154  owl_function_makemsg("Waiting for ack...");
155
156  /* display the message as an admin message in the receive window */
157  if (owl_global_is_displayoutgoing(&g) && owl_zwrite_is_personal(&z)) {
158    owl_zwrite_get_recipstr(&z, buff);
159    tmpbuff = owl_sprintf("Message sent to %s", buff);
160    owl_function_adminmsg_outgoing(tmpbuff, owl_editwin_get_text(owl_global_get_typwin(&g)), line);
161    owl_free(tmpbuff);
162  }
163
164  /* log it if we have logging turned on */
165  if (owl_global_is_logging(&g) && owl_zwrite_is_personal(&z)) {
166    j=owl_zwrite_get_numrecips(&z);
167    for (i=0; i<j; i++) {
168      owl_log_outgoing(owl_zwrite_get_recip_n(&z, i),
169                       owl_editwin_get_text(owl_global_get_typwin(&g)));
170    }
171  }
172
173  /* free the zwrite */
174  owl_zwrite_free(&z);
175}
176
177
178/* If filter is non-null, looks for the next message matching
179 * that filter.  If skip_deleted, skips any deleted messages.
180 * If last_if_none, will stop at the last message in the view
181 * if no matching messages are found.  */
182void owl_function_nextmsg_full(char *filter, int skip_deleted, int last_if_none) {
183  int curmsg, i, viewsize, found;
184  owl_view *v;
185  owl_filter *f = NULL;
186  owl_message *m;
187
188  v=owl_global_get_current_view(&g);
189
190  if (filter) {
191    f=owl_global_get_filter(&g, filter);
192    if (!f) {
193      owl_function_makemsg("No %s filter defined", filter);
194      return;
195    }
196  }
197
198  curmsg=owl_global_get_curmsg(&g);
199  viewsize=owl_view_get_size(v);
200  found=0;
201
202  /* just check to make sure we're in bounds... */
203  if (curmsg>viewsize-1) curmsg=viewsize-1;
204  if (curmsg<0) curmsg=0;
205
206  for (i=curmsg+1; i<viewsize; i++) {
207    m=owl_view_get_element(v, i);
208    if (skip_deleted && owl_message_is_delete(m)) continue;
209    if (f && !owl_filter_message_match(f, m)) continue;
210    found = 1;
211    break;
212  }
213
214  if (i>owl_view_get_size(v)-1) i=owl_view_get_size(v)-1;
215
216  if (!found) {
217    owl_function_makemsg("already at last%s message%s%s",
218                         skip_deleted?" non-deleted":"",
219                         filter?" in ":"", filter?filter:"");
220    if (!skip_deleted) owl_function_beep();
221  }
222
223  if (last_if_none || found) {
224    owl_global_set_curmsg(&g, i);
225    owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
226    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
227    owl_global_set_direction_downwards(&g);
228  }
229}
230
231void owl_function_prevmsg_full(char *filter, int skip_deleted, int first_if_none) {
232  int curmsg, i, viewsize, found;
233  owl_view *v;
234  owl_filter *f = NULL;
235  owl_message *m;
236
237  v=owl_global_get_current_view(&g);
238
239  if (filter) {
240    f=owl_global_get_filter(&g, filter);
241    if (!f) {
242      owl_function_makemsg("No %s filter defined", filter);
243      return;
244    }
245  }
246
247  curmsg=owl_global_get_curmsg(&g);
248  viewsize=owl_view_get_size(v);
249  found=0;
250
251  /* just check to make sure we're in bounds... */
252  if (curmsg>viewsize-1) curmsg=viewsize-1;
253  if (curmsg<0) curmsg=0;
254
255  for (i=curmsg-1; i>=0; i--) {
256    m=owl_view_get_element(v, i);
257    if (skip_deleted && owl_message_is_delete(m)) continue;
258    if (f && !owl_filter_message_match(f, m)) continue;
259    found = 1;
260    break;
261  }
262
263  if (i<0) i=0;
264
265  if (!found) {
266    owl_function_makemsg("already at first%s message%s%s",
267                         skip_deleted?" non-deleted":"",
268                         filter?" in ":"", filter?filter:"");
269    if (!skip_deleted) owl_function_beep();
270  }
271
272  if (first_if_none || found) {
273    owl_global_set_curmsg(&g, i);
274    owl_function_calculate_topmsg(OWL_DIRECTION_UPWARDS);
275    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
276    owl_global_set_direction_upwards(&g);
277  }
278}
279
280void owl_function_nextmsg() {
281  owl_function_nextmsg_full(NULL, 0, 1);
282}
283
284
285void owl_function_prevmsg() {
286  owl_function_prevmsg_full(NULL, 0, 1);
287}
288
289void owl_function_nextmsg_notdeleted() {
290  owl_function_nextmsg_full(NULL, 1, 1);
291}
292
293
294void owl_function_prevmsg_notdeleted() {
295  owl_function_prevmsg_full(NULL, 1, 1);
296}
297
298
299void owl_function_nextmsg_personal() {
300  owl_function_nextmsg_full("personal", 0, 0);
301}
302
303void owl_function_prevmsg_personal() {
304  owl_function_prevmsg_full("personal", 0, 0);
305}
306
307
308/* if move_after is 1, moves after the delete */
309void owl_function_deletecur(int move_after) {
310  int curmsg;
311  owl_view *v;
312
313  v=owl_global_get_current_view(&g);
314
315  /* bail if there's no current message */
316  if (owl_view_get_size(v) < 1) {
317    owl_function_makemsg("No current message to delete");
318    return;
319  }
320
321  /* mark the message for deletion */
322  curmsg=owl_global_get_curmsg(&g);
323  owl_view_delete_element(v, curmsg);
324
325  if (move_after) {
326    /* move the poiner in the appropriate direction
327     * to the next undeleted msg */
328    if (owl_global_get_direction(&g)==OWL_DIRECTION_UPWARDS) {
329      owl_function_prevmsg_notdeleted();
330    } else {
331      owl_function_nextmsg_notdeleted();
332    }
333  }
334}
335
336
337void owl_function_undeletecur(int move_after) {
338  int curmsg;
339  owl_view *v;
340
341  v=owl_global_get_current_view(&g);
342 
343  if (owl_view_get_size(v) < 1) {
344    owl_function_makemsg("No current message to undelete");
345    return;
346  }
347  curmsg=owl_global_get_curmsg(&g);
348
349  owl_view_undelete_element(v, curmsg);
350
351  if (move_after) {
352    if (owl_global_get_direction(&g)==OWL_DIRECTION_UPWARDS) {
353      if (curmsg>0) {
354        owl_function_prevmsg();
355      } else {
356        owl_function_nextmsg();
357      }
358    } else {
359      owl_function_nextmsg();
360    }
361  }
362
363  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
364}
365
366
367void owl_function_expunge() {
368  int curmsg;
369  owl_message *m;
370  owl_messagelist *ml;
371  owl_view *v;
372  int i, j;
373
374  curmsg=owl_global_get_curmsg(&g);
375  v=owl_global_get_current_view(&g);
376  ml=owl_global_get_msglist(&g);
377
378  /* first try to move to an undeleted message in the view*/
379  m=owl_view_get_element(v, curmsg);
380  if (owl_message_is_delete(m)) {
381    /* try to find the next undeleted message */
382    j=owl_view_get_size(v);
383    for (i=curmsg; i<j; i++) {
384      if (!owl_message_is_delete(owl_view_get_element(v, i))) {
385        owl_global_set_curmsg(&g, i);
386        break;
387      }
388    }
389
390    /* if we weren't successful try to find one backwards */
391    curmsg=owl_global_get_curmsg(&g);
392    if (owl_message_is_delete(owl_view_get_element(v, curmsg))) {
393      for (i=curmsg; i>0; i--) {
394        if (!owl_message_is_delete(owl_view_get_element(v, i))) {
395          owl_global_set_curmsg(&g, i);
396          break;
397        }
398      }
399    }
400  }
401
402  /* expunge the message list */
403  owl_messagelist_expunge(ml);
404
405  /* update all views (we only have one right now) */
406  owl_view_recalculate(v);
407
408  if (curmsg>owl_view_get_size(v)-1) {
409    owl_global_set_curmsg(&g, owl_view_get_size(v)-1);
410    if (owl_global_get_curmsg(&g)<0) {
411      owl_global_set_curmsg(&g, 0);
412    }
413    owl_function_calculate_topmsg(OWL_DIRECTION_NONE);
414  }
415
416  /* if there are no messages set the direction to down in case we
417     delete everything upwards */
418  owl_global_set_direction_downwards(&g);
419 
420  owl_function_makemsg("Messages expunged");
421  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
422}
423
424
425void owl_function_firstmsg() {
426  owl_global_set_curmsg(&g, 0);
427  owl_global_set_topmsg(&g, 0);
428  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
429  owl_global_set_direction_downwards(&g);
430}
431
432void owl_function_lastmsg_noredisplay() {
433  int curmsg;
434  owl_view *v;
435
436  v=owl_global_get_current_view(&g);
437 
438  curmsg=owl_view_get_size(v)-1;
439  if (curmsg<0) curmsg=0;
440  owl_global_set_curmsg(&g, curmsg);
441  owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
442  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
443  owl_global_set_direction_downwards(&g);
444}
445
446void owl_function_lastmsg() {
447  owl_function_lastmsg_noredisplay();
448  owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 
449}
450
451void owl_function_shift_right() {
452  owl_global_set_rightshift(&g, owl_global_get_rightshift(&g)+10);
453  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
454  owl_global_set_needrefresh(&g);
455}
456
457
458void owl_function_shift_left() {
459  int shift;
460
461  shift=owl_global_get_rightshift(&g);
462  if (shift>=10) {
463    owl_global_set_rightshift(&g, shift-10);
464    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
465    owl_global_set_needrefresh(&g);
466  } else {
467    owl_function_beep();
468    owl_function_makemsg("Already full left");
469  }
470}
471
472
473void owl_function_unsuball() {
474  unsuball();
475  owl_function_makemsg("Unsubscribed from all messages.");
476}
477
478void owl_function_loadsubs(char *file) {
479  int ret;
480  ret=owl_zephyr_loadsubs(file);
481  if (ret==0) {
482    owl_function_makemsg("Subscribed to messages from file.");
483  } else if (ret==-1) {
484    owl_function_makemsg("Could not open file.");
485  } else {
486    owl_function_makemsg("Error subscribing to messages from file.");
487  }
488}
489
490void owl_function_suspend() {
491  endwin();
492  printf("\n");
493  kill(getpid(), SIGSTOP);
494
495  /* resize to reinitialize all the windows when we come back */
496  owl_command_resize();
497}
498
499void owl_function_zaway_toggle() {
500  if (!owl_global_is_zaway(&g)) {
501    owl_global_set_zaway_msg(&g, owl_global_get_zaway_msg_default(&g));
502    owl_function_zaway_on();
503  } else {
504    owl_function_zaway_off();
505  }
506}
507
508void owl_function_zaway_on() {
509  owl_global_set_zaway_on(&g);
510  owl_function_makemsg("zaway set (%s)", owl_global_get_zaway_msg(&g));
511}
512
513void owl_function_zaway_off() {
514  owl_global_set_zaway_off(&g);
515  owl_function_makemsg("zaway off");
516}
517
518void owl_function_quit() {
519  char *ret;
520 
521  /* zlog out if we need to */
522  if (owl_global_is_shutdownlogout(&g)) {
523    owl_function_zlog_out();
524  }
525
526  /* execute the commands in shutdown */
527  ret = owl_config_execute("owl::shutdown();");
528  if (ret) owl_free(ret);
529
530  /* final clean up */
531  unsuball();
532  ZClosePort();
533  endwin();
534  owl_function_debugmsg("Quitting Owl");
535  exit(0);
536}
537
538
539void owl_function_zlog_in() {
540  char *exposure, *eset;
541  int ret;
542
543  eset=EXPOSE_REALMVIS;
544  exposure=ZGetVariable("exposure");
545  if (exposure==NULL) {
546    eset=EXPOSE_REALMVIS;
547  } else if (!strcasecmp(exposure,EXPOSE_NONE)) {
548    eset = EXPOSE_NONE;
549  } else if (!strcasecmp(exposure,EXPOSE_OPSTAFF)) {
550    eset = EXPOSE_OPSTAFF;
551  } else if (!strcasecmp(exposure,EXPOSE_REALMVIS)) {
552    eset = EXPOSE_REALMVIS;
553  } else if (!strcasecmp(exposure,EXPOSE_REALMANN)) {
554    eset = EXPOSE_REALMANN;
555  } else if (!strcasecmp(exposure,EXPOSE_NETVIS)) {
556    eset = EXPOSE_NETVIS;
557  } else if (!strcasecmp(exposure,EXPOSE_NETANN)) {
558    eset = EXPOSE_NETANN;
559  }
560   
561  ret=ZSetLocation(eset);
562  if (ret != ZERR_NONE) {
563    /*
564      char buff[LINE];
565      sprintf(buff, "Error setting location: %s", error_message(ret));
566      owl_function_makemsg(buff);
567    */
568  }
569}
570
571void owl_function_zlog_out() {
572  int ret;
573 
574  ret=ZUnsetLocation();
575  if (ret != ZERR_NONE) {
576    /*
577      char buff[LINE];
578      sprintf(buff, "Error unsetting location: %s", error_message(ret));
579      owl_function_makemsg(buff);
580    */
581  }
582}
583
584
585void owl_function_makemsg(char *fmt, ...) {
586  va_list ap;
587  char buff[2048];
588
589  va_start(ap, fmt);
590  werase(owl_global_get_curs_msgwin(&g));
591 
592  vsnprintf(buff, 2048, fmt, ap);
593  owl_function_debugmsg("makemsg: %s", buff);
594  waddstr(owl_global_get_curs_msgwin(&g), buff); 
595  wnoutrefresh(owl_global_get_curs_msgwin(&g));
596  owl_global_set_needrefresh(&g);
597  va_end(ap);
598}
599
600void owl_function_errormsg(char *fmt, ...) {
601  va_list ap;
602  char buff[2048];
603
604  va_start(ap, fmt);
605  werase(owl_global_get_curs_msgwin(&g));
606 
607  vsnprintf(buff, 2048, fmt, ap);
608  owl_function_debugmsg("ERROR: %s", buff);
609  waddstr(owl_global_get_curs_msgwin(&g), buff); 
610  waddstr(owl_global_get_curs_msgwin(&g), "ERROR: "); 
611  wnoutrefresh(owl_global_get_curs_msgwin(&g));
612  owl_global_set_needrefresh(&g);
613  va_end(ap);
614}
615
616
617void owl_function_openurl() {
618  /* visit the first url in the current message */
619  owl_message *m;
620  owl_view *v;
621  char *ptr1, *ptr2, *text, url[LINE], tmpbuff[LINE];
622  int webbrowser;
623
624  webbrowser = owl_global_get_webbrowser(&g);
625
626  if (webbrowser < 0 || webbrowser == OWL_WEBBROWSER_NONE) {
627    owl_function_makemsg("No browser selected");
628    return;
629  }
630
631  v=owl_global_get_current_view(&g);
632 
633  if (owl_view_get_size(v)==0) {
634    owl_function_makemsg("No current message selected");
635    return;
636  }
637
638  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
639  text=owl_message_get_text(m);
640
641  /* First look for a good URL */ 
642  if ((ptr1=strstr(text, "http://"))!=NULL) {
643    ptr2=strpbrk(ptr1, " \n\t");
644    if (ptr2) {
645      strncpy(url, ptr1, ptr2-ptr1+1);
646      url[ptr2-ptr1+1]='\0';
647    } else {
648      strcpy(url, ptr1);
649    }
650
651    /* if we had <http strip a trailing > */
652    if (ptr1>text && ptr1[-1]=='<') {
653      if (url[strlen(url)-1]=='>') {
654        url[strlen(url)-1]='\0';
655      }
656    }
657  } else if ((ptr1=strstr(text, "https://"))!=NULL) {
658    /* Look for an https URL */ 
659    ptr2=strpbrk(ptr1, " \n\t");
660    if (ptr2) {
661      strncpy(url, ptr1, ptr2-ptr1+1);
662      url[ptr2-ptr1+1]='\0';
663    } else {
664      strcpy(url, ptr1);
665    }
666   
667    /* if we had <http strip a trailing > */
668    if (ptr1>text && ptr1[-1]=='<') {
669      if (url[strlen(url)-1]=='>') {
670        url[strlen(url)-1]='\0';
671      }
672    }
673  } else if ((ptr1=strstr(text, "www."))!=NULL) {
674    /* if we can't find a real url look for www.something */
675    ptr2=strpbrk(ptr1, " \n\t");
676    if (ptr2) {
677      strncpy(url, ptr1, ptr2-ptr1+1);
678      url[ptr2-ptr1+1]='\0';
679    } else {
680      strcpy(url, ptr1);
681    }
682  } else {
683    owl_function_beep();
684    owl_function_makemsg("Could not find URL to open.");
685    return;
686  }
687
688  /* Make sure there aren't any quotes or \'s in the url */
689  for (ptr1 = url; *ptr1; ptr1++) {
690    if (*ptr1 == '"' || *ptr1 == '\\') {
691      owl_function_beep();
692      owl_function_makemsg("URL contains invalid characters.");
693      return;
694    }
695  }
696 
697  /* NOTE: There are potentially serious security issues here... */
698
699  /* open the page */
700  owl_function_makemsg("Opening %s", url);
701  if (webbrowser == OWL_WEBBROWSER_NETSCAPE) {
702    snprintf(tmpbuff, LINE, "netscape -remote \"openURL(%s)\" > /dev/null 2> /dev/null", url);
703    system(tmpbuff); 
704  } else if (webbrowser == OWL_WEBBROWSER_GALEON) {
705    snprintf(tmpbuff, LINE, "galeon \"%s\" > /dev/null 2> /dev/null &", url);
706    system(tmpbuff); 
707  } else if (webbrowser == OWL_WEBBROWSER_OPERA) {
708    snprintf(tmpbuff, LINE, "opera \"%s\" > /dev/null 2> /dev/null &", url);
709    system(tmpbuff); 
710  }
711}
712
713void owl_function_calculate_topmsg(int direction) {
714  int recwinlines, topmsg, curmsg;
715  owl_view *v;
716
717  v=owl_global_get_current_view(&g);
718  curmsg=owl_global_get_curmsg(&g);
719  topmsg=owl_global_get_topmsg(&g);
720  recwinlines=owl_global_get_recwin_lines(&g);
721
722  if (owl_view_get_size(v) < 1) {
723    return;
724  }
725
726  switch (owl_global_get_scrollmode(&g)) {
727  case OWL_SCROLLMODE_TOP:
728    topmsg = owl_function_calculate_topmsg_top(direction, v, curmsg,
729                                               topmsg, recwinlines);
730    break;
731  case OWL_SCROLLMODE_NEARTOP:
732    topmsg = owl_function_calculate_topmsg_neartop(direction, v, curmsg, 
733                                                   topmsg, recwinlines);
734    break;
735  case OWL_SCROLLMODE_CENTER:
736    topmsg = owl_function_calculate_topmsg_center(direction, v, curmsg,
737                                                  topmsg, recwinlines);
738    break;
739  case OWL_SCROLLMODE_PAGED:
740    topmsg = owl_function_calculate_topmsg_paged(direction, v, curmsg, 
741                                                 topmsg, recwinlines, 0);
742    break;
743  case OWL_SCROLLMODE_PAGEDCENTER:
744    topmsg = owl_function_calculate_topmsg_paged(direction, v, curmsg, 
745                                                 topmsg, recwinlines, 1);
746    break;
747  case OWL_SCROLLMODE_NORMAL:
748  default:
749    topmsg = owl_function_calculate_topmsg_normal(direction, v, curmsg,
750                                                  topmsg, recwinlines);
751  }
752  owl_global_set_topmsg(&g, topmsg);
753}
754
755/* Returns what the new topmsg should be. 
756 * Passed the last direction of movement,
757 * the current view,
758 * the current message number in the view,
759 * the top message currently being displayed,
760 * and the number of lines in the recwin.
761 */
762int owl_function_calculate_topmsg_top(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines) {
763  return curmsg;
764}
765
766int owl_function_calculate_topmsg_neartop(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines) {
767  if (curmsg>0 
768      && (owl_message_get_numlines(owl_view_get_element(v, curmsg-1))
769          <  recwinlines/2)) {
770    return curmsg-1;
771  } else {
772    return curmsg;
773  }
774}
775 
776int owl_function_calculate_topmsg_center(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines) {
777  int i, last, lines;
778
779  last = curmsg;
780  lines = 0;
781  for (i=curmsg-1; i>=0; i--) {
782    lines += owl_message_get_numlines(owl_view_get_element(v, i));
783    if (lines > recwinlines/2) break;
784    last = i;
785  }
786  return last;
787}
788 
789int owl_function_calculate_topmsg_paged(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines, int center_on_page) {
790  int i, last, lines, savey;
791 
792  /* If we're off the top of the screen, scroll up such that the
793   * curmsg is near the botton of the screen. */
794  if (curmsg < topmsg) {
795    last = curmsg;
796    lines = 0;
797    for (i=curmsg; i>=0; i--) {
798      lines += owl_message_get_numlines(owl_view_get_element(v, i));
799      if (lines > recwinlines) break;
800    last = i;
801    }
802    if (center_on_page) {
803      return owl_function_calculate_topmsg_center(direction, v, curmsg, 0, recwinlines);
804    } else {
805      return last;
806    }
807  }
808
809  /* Find number of lines from top to bottom of curmsg (store in savey) */
810  savey=0;
811  for (i=topmsg; i<=curmsg; i++) {
812    savey+=owl_message_get_numlines(owl_view_get_element(v, i));
813  }
814
815  /* if we're off the bottom of the screen, scroll down */
816  if (savey > recwinlines) {
817    if (center_on_page) {
818      return owl_function_calculate_topmsg_center(direction, v, curmsg, 0, recwinlines);
819    } else {
820      return curmsg;
821    }
822  }
823
824  /* else just stay as we are... */
825  return topmsg;
826}
827
828
829int owl_function_calculate_topmsg_normal(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines) {
830  int savey, j, i, foo, y;
831 
832  /* Find number of lines from top to bottom of curmsg (store in savey) */
833  savey=0;
834  for (i=topmsg; i<=curmsg; i++) {
835    savey+=owl_message_get_numlines(owl_view_get_element(v, i));
836  }
837
838  /* If the direction is DOWNWARDS but we're off the bottom of the
839   *  screen, then set the topmsg to curmsg and scroll UPWARDS
840   */
841  if (direction == OWL_DIRECTION_DOWNWARDS) {
842    if (savey > recwinlines) {
843      topmsg=curmsg;
844      savey=owl_message_get_numlines(owl_view_get_element(v, i));
845      direction=OWL_DIRECTION_UPWARDS;
846    }
847  }
848
849  /* If our bottom line is less than 1/4 down the screen then scroll up */
850  if (direction == OWL_DIRECTION_UPWARDS || direction == OWL_DIRECTION_NONE) {
851    if (savey < (recwinlines / 4)) {
852      y=0;
853      for (j=curmsg; j>=0; j--) {
854        foo=owl_message_get_numlines(owl_view_get_element(v, j));
855        /* will we run the curmsg off the screen? */
856        if ((foo+y) >= recwinlines) {
857          j++;
858          if (j>curmsg) j=curmsg;
859          break;
860        }
861        /* have saved 1/2 the screen space? */
862        y+=foo;
863        if (y > (recwinlines / 2)) break;
864      }
865      if (j<0) j=0;
866      return j;
867    }
868  }
869
870  if (direction == OWL_DIRECTION_DOWNWARDS || direction == OWL_DIRECTION_NONE) {
871    /* If curmsg bottom line is more than 3/4 down the screen then scroll down */
872    if (savey > ((recwinlines * 3)/4)) {
873      y=0;
874      /* count lines from the top until we can save 1/2 the screen size */
875      for (j=topmsg; j<curmsg; j++) {
876        y+=owl_message_get_numlines(owl_view_get_element(v, j));
877        if (y > (recwinlines / 2)) break;
878      }
879      if (j==curmsg) {
880        j--;
881      }
882      return j+1;
883    }
884  }
885
886  return topmsg;
887}
888
889
890void owl_function_resize() {
891  owl_global_set_resize_pending(&g);
892}
893
894
895void owl_function_run_buffercommand() {
896  char *buff;
897
898  buff=owl_global_get_buffercommand(&g);
899  if (!strncmp(buff, "zwrite ", 7)) {
900
901    owl_function_zwrite(buff);
902  }
903}
904
905void owl_function_debugmsg(char *fmt, ...) {
906  FILE *file;
907  time_t now;
908  char buff1[LINE], buff2[LINE];
909  va_list ap;
910  va_start(ap, fmt);
911
912  if (!owl_global_is_debug_fast(&g)) return;
913
914  file=fopen(owl_global_get_debug_file(&g), "a");
915  if (!file) return;
916
917  now=time(NULL);
918  strcpy(buff1, ctime(&now));
919  buff1[strlen(buff1)-1]='\0';
920
921  owl_global_get_runtime_string(&g, buff2);
922 
923  fprintf(file, "[%i -  %s - %s]: ", (int) getpid(), buff1, buff2);
924  vfprintf(file, fmt, ap);
925  fprintf(file, "\n");
926  fclose(file);
927
928  va_end(ap);
929}
930
931
932void owl_function_refresh() {
933  owl_function_resize();
934}
935
936void owl_function_beep() {
937  if (owl_global_is_bell(&g)) {
938    beep();
939  }
940}
941
942
943void owl_function_subscribe(char *class, char *inst, char *recip) {
944  int ret;
945
946  ret=owl_zephyr_sub(class, inst, recip);
947  if (ret) {
948    owl_function_makemsg("Error subscribing.");
949  } else {
950    owl_function_makemsg("Subscribed.");
951  }
952}
953
954
955void owl_function_unsubscribe(char *class, char *inst, char *recip) {
956  int ret;
957
958  ret=owl_zephyr_unsub(class, inst, recip);
959  if (ret) {
960    owl_function_makemsg("Error subscribing.");
961  } else {
962    owl_function_makemsg("Unsubscribed.");
963  }
964}
965
966
967void owl_function_set_cursor(WINDOW *win) {
968  wnoutrefresh(win);
969}
970
971
972void owl_function_full_redisplay() {
973  redrawwin(owl_global_get_curs_recwin(&g));
974  redrawwin(owl_global_get_curs_sepwin(&g));
975  redrawwin(owl_global_get_curs_typwin(&g));
976  redrawwin(owl_global_get_curs_msgwin(&g));
977
978  wnoutrefresh(owl_global_get_curs_recwin(&g));
979  wnoutrefresh(owl_global_get_curs_sepwin(&g));
980  wnoutrefresh(owl_global_get_curs_typwin(&g));
981  wnoutrefresh(owl_global_get_curs_msgwin(&g));
982 
983  sepbar("");
984  owl_function_makemsg("");
985
986  owl_global_set_needrefresh(&g);
987}
988
989
990void owl_function_popless_text(char *text) {
991  owl_popwin *pw;
992  owl_viewwin *v;
993
994  pw=owl_global_get_popwin(&g);
995  v=owl_global_get_viewwin(&g);
996
997  owl_popwin_up(pw);
998  owl_viewwin_init_text(v, owl_popwin_get_curswin(pw),
999                        owl_popwin_get_lines(pw), owl_popwin_get_cols(pw),
1000                        text);
1001  owl_popwin_refresh(pw);
1002  owl_viewwin_redisplay(v, 0);
1003  owl_global_set_needrefresh(&g);
1004}
1005
1006
1007void owl_function_popless_fmtext(owl_fmtext *fm) {
1008  owl_popwin *pw;
1009  owl_viewwin *v;
1010
1011  pw=owl_global_get_popwin(&g);
1012  v=owl_global_get_viewwin(&g);
1013
1014  owl_popwin_up(pw);
1015  owl_viewwin_init_fmtext(v, owl_popwin_get_curswin(pw),
1016                   owl_popwin_get_lines(pw), owl_popwin_get_cols(pw),
1017                   fm);
1018  owl_popwin_refresh(pw);
1019  owl_viewwin_redisplay(v, 0);
1020  owl_global_set_needrefresh(&g);
1021}
1022
1023void owl_function_about() {
1024  char buff[5000];
1025
1026  sprintf(buff, "This is owl version %s\n", OWL_VERSION_STRING);
1027  strcat(buff, "\nOwl was written by James Kretchmar at the Massachusetts\n");
1028  strcat(buff, "Institute of Technology.  The first version, 0.5, was\n");
1029  strcat(buff, "released in March 2002\n");
1030  strcat(buff, "\n");
1031  strcat(buff, "The name 'owl' was chosen in reference to the owls in the\n");
1032  strcat(buff, "Harry Potter novels, who are tasked with carrying messages\n");
1033  strcat(buff, "between Witches and Wizards.\n");
1034  strcat(buff, "\n");
1035  strcat(buff, "Copyright 2002 Massachusetts Institute of Technology\n");
1036  strcat(buff, "\n");
1037  strcat(buff, "Permission to use, copy, modify, and distribute this\n");
1038  strcat(buff, "software and its documentation for any purpose and without\n");
1039  strcat(buff, "fee is hereby granted, provided that the above copyright\n");
1040  strcat(buff, "notice and this permission notice appear in all copies\n");
1041  strcat(buff, "and in supporting documentation.  No representation is\n");
1042  strcat(buff, "made about the suitability of this software for any\n");
1043  strcat(buff, "purpose.  It is provided \"as is\" without express\n");
1044  strcat(buff, "or implied warranty.\n");
1045  owl_function_popless_text(buff);
1046}
1047
1048void owl_function_info() {
1049  owl_message *m;
1050  ZNotice_t *n;
1051  char buff[2048], tmpbuff[1024];
1052  char *ptr;
1053  int i, j, fields, len;
1054  owl_view *v;
1055
1056  v=owl_global_get_current_view(&g);
1057 
1058  if (owl_view_get_size(v)==0) {
1059    owl_function_makemsg("No message selected\n");
1060    return;
1061  }
1062
1063  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
1064  if (!owl_message_is_zephyr(m)) {
1065    sprintf(buff,   "Owl Message Id: %i\n", owl_message_get_id(m));
1066    sprintf(buff, "%sTime          : %s\n", buff, owl_message_get_timestr(m));
1067    owl_function_popless_text(buff);
1068    return;
1069  }
1070
1071  n=owl_message_get_notice(m);
1072
1073  sprintf(buff,   "Owl Msg ID: %i\n", owl_message_get_id(m));
1074  sprintf(buff, "%sClass     : %s\n", buff, n->z_class);
1075  sprintf(buff, "%sInstance  : %s\n", buff, n->z_class_inst);
1076  sprintf(buff, "%sSender    : %s\n", buff, n->z_sender);
1077  sprintf(buff, "%sRecip     : %s\n", buff, n->z_recipient);
1078  sprintf(buff, "%sOpcode    : %s\n", buff, n->z_opcode);
1079  strcat(buff,    "Kind      : ");
1080  if (n->z_kind==UNSAFE) {
1081    strcat(buff, "UNSAFE\n");
1082  } else if (n->z_kind==UNACKED) {
1083    strcat(buff, "UNACKED\n");
1084  } else if (n->z_kind==ACKED) {
1085    strcat(buff, "ACKED\n");
1086  } else if (n->z_kind==HMACK) {
1087    strcat(buff, "HMACK\n");
1088  } else if (n->z_kind==HMCTL) {
1089    strcat(buff, "HMCTL\n");
1090  } else if (n->z_kind==SERVACK) {
1091    strcat(buff, "SERVACK\n");
1092  } else if (n->z_kind==SERVNAK) {
1093    strcat(buff, "SERVNAK\n");
1094  } else if (n->z_kind==CLIENTACK) {
1095    strcat(buff, "CLIENTACK\n");
1096  } else if (n->z_kind==STAT) {
1097    strcat(buff, "STAT\n");
1098  } else {
1099    strcat(buff, "ILLEGAL VALUE\n");
1100  }
1101  sprintf(buff, "%sTime      : %s\n", buff, owl_message_get_timestr(m));
1102  sprintf(buff, "%sHost      : %s\n", buff, owl_message_get_hostname(m));
1103  sprintf(buff, "%sPort      : %i\n", buff, n->z_port);
1104  strcat(buff,    "Auth      : ");
1105  if (n->z_auth == ZAUTH_FAILED) {
1106    strcat(buff, "FAILED\n");
1107  } else if (n->z_auth == ZAUTH_NO) {
1108    strcat(buff, "NO\n");
1109  } else if (n->z_auth == ZAUTH_YES) {
1110    strcat(buff, "YES\n");
1111  } else {
1112    sprintf(buff, "%sUnknown State (%i)\n", buff, n->z_auth);
1113  }
1114  sprintf(buff, "%sCheckd Ath: %i\n", buff, n->z_checked_auth);
1115  sprintf(buff, "%sMulti notc: %s\n", buff, n->z_multinotice);
1116  sprintf(buff, "%sNum other : %i\n", buff, n->z_num_other_fields);
1117  sprintf(buff, "%sMsg Len   : %i\n", buff, n->z_message_len);
1118
1119  sprintf(buff, "%sFields    : %i\n", buff, owl_zephyr_get_num_fields(n));
1120
1121  fields=owl_zephyr_get_num_fields(n);
1122  for (i=0; i<fields; i++) {
1123    sprintf(buff, "%sField %i   : ", buff, i+1);
1124
1125    ptr=owl_zephyr_get_field(n, i+1, &len);
1126    if (!ptr) break;
1127    if (len<30) {
1128      strncpy(tmpbuff, ptr, len);
1129      tmpbuff[len]='\0';
1130    } else {
1131      strncpy(tmpbuff, ptr, 30);
1132      tmpbuff[30]='\0';
1133      strcat(tmpbuff, "...");
1134    }
1135
1136    /* just for testing for now */
1137    for (j=0; j<strlen(tmpbuff); j++) {
1138      if (tmpbuff[j]=='\n') tmpbuff[j]='~';
1139      if (tmpbuff[j]=='\r') tmpbuff[j]='!';
1140    }
1141
1142    strcat(buff, tmpbuff);
1143    strcat(buff, "\n");
1144  }
1145  sprintf(buff, "%sDefault Fm: %s\n", buff, n->z_default_format);
1146       
1147  owl_function_popless_text(buff);
1148}
1149
1150
1151void owl_function_curmsg_to_popwin() {
1152  owl_popwin *pw;
1153  owl_view *v;
1154  owl_message *m;
1155
1156  v = owl_global_get_current_view(&g);
1157
1158  pw=owl_global_get_popwin(&g);
1159
1160  if (owl_view_get_size(v)==0) {
1161    owl_function_makemsg("No current message");
1162    return;
1163  }
1164
1165  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
1166  owl_function_popless_fmtext(owl_message_get_fmtext(m));
1167}
1168
1169
1170void owl_function_page_curmsg(int step) {
1171  /* scroll down or up within the current message IF the message is truncated */
1172
1173  int offset, curmsg, lines;
1174  owl_view *v;
1175  owl_message *m;
1176
1177  offset=owl_global_get_curmsg_vert_offset(&g);
1178  v=owl_global_get_current_view(&g);
1179  if (owl_view_get_size(v)==0) return;
1180  curmsg=owl_global_get_curmsg(&g);
1181  m=owl_view_get_element(v, curmsg);
1182  lines=owl_message_get_numlines(m);
1183
1184  if (offset==0) {
1185    /* Bail if the curmsg isn't the last one displayed */
1186    if (curmsg != owl_mainwin_get_last_msg(owl_global_get_mainwin(&g))) {
1187      owl_function_makemsg("The entire message is already displayed");
1188      return;
1189    }
1190   
1191    /* Bail if we're not truncated */
1192    if (!owl_mainwin_is_curmsg_truncated(owl_global_get_mainwin(&g))) {
1193      owl_function_makemsg("The entire message is already displayed");
1194      return;
1195    }
1196  }
1197 
1198 
1199  /* don't scroll past the last line */
1200  if (step>0) {
1201    if (offset+step > lines-1) {
1202      owl_global_set_curmsg_vert_offset(&g, lines-1);
1203    } else {
1204      owl_global_set_curmsg_vert_offset(&g, offset+step);
1205    }
1206  }
1207
1208  /* would we be before the beginning of the message? */
1209  if (step<0) {
1210    if (offset+step<0) {
1211      owl_global_set_curmsg_vert_offset(&g, 0);
1212    } else {
1213      owl_global_set_curmsg_vert_offset(&g, offset+step);
1214    }
1215  }
1216 
1217  /* redisplay */
1218  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1219  owl_global_set_needrefresh(&g);
1220}
1221
1222void owl_function_resize_typwin(int newsize) {
1223  owl_global_set_typwin_lines(&g, newsize);
1224  owl_function_resize();
1225}
1226
1227void owl_function_typwin_grow() {
1228  int i;
1229
1230  i=owl_global_get_typwin_lines(&g);
1231  owl_function_resize_typwin(i+1);
1232}
1233
1234void owl_function_typwin_shrink() {
1235  int i;
1236
1237  i=owl_global_get_typwin_lines(&g);
1238  if (i>2) {
1239    owl_function_resize_typwin(i-1);
1240  }
1241}
1242
1243void owl_function_mainwin_pagedown() {
1244  int i;
1245
1246  i=owl_mainwin_get_last_msg(owl_global_get_mainwin(&g));
1247  if (i<0) return;
1248  if (owl_mainwin_is_last_msg_truncated(owl_global_get_mainwin(&g))
1249      && (owl_global_get_curmsg(&g) < i)
1250      && (i>0)) {
1251    i--;
1252  }
1253  owl_global_set_curmsg(&g, i);
1254  owl_function_nextmsg();
1255}
1256
1257void owl_function_mainwin_pageup() {
1258  owl_global_set_curmsg(&g, owl_global_get_topmsg(&g));
1259  owl_function_prevmsg();
1260}
1261
1262void owl_function_getsubs() {
1263  int ret, num, i, one;
1264  ZSubscription_t sub;
1265  char *buff;
1266
1267  one = 1;
1268
1269  ret=ZRetrieveSubscriptions(0, &num);
1270  if (ret == ZERR_TOOMANYSUBS) {
1271
1272  }
1273
1274  buff=owl_malloc(num*200);
1275  strcpy(buff, "");
1276  for (i=0; i<num; i++) {
1277    if ((ret = ZGetSubscriptions(&sub, &one)) != ZERR_NONE) {
1278      /* deal with error */
1279    } else {
1280      sprintf(buff, "%s<%s,%s,%s>\n", buff, sub.zsub_class, sub.zsub_classinst, sub.zsub_recipient);
1281    }
1282  }
1283
1284  owl_function_popless_text(buff);
1285  owl_free(buff);
1286  ZFlushSubscriptions();
1287}
1288
1289#define PABUFLEN 5000
1290void owl_function_printallvars() {
1291  char buff[PABUFLEN], *pos, *name;
1292  owl_list varnames;
1293  int i, numvarnames, rem;
1294
1295  pos = buff;
1296  pos += sprintf(pos, "%-20s = %s\n", "VARIABLE", "VALUE");
1297  pos += sprintf(pos, "%-20s   %s\n",  "--------", "-----");
1298  owl_variable_dict_get_names(owl_global_get_vardict(&g), &varnames);
1299  rem = (buff+PABUFLEN)-pos-1;
1300  numvarnames = owl_list_get_size(&varnames);
1301  for (i=0; i<numvarnames; i++) {
1302    name = owl_list_get_element(&varnames, i);
1303    if (name && name[0]!='_') {
1304      rem = (buff+PABUFLEN)-pos-1;   
1305      pos += snprintf(pos, rem, "\n%-20s = ", name);
1306      rem = (buff+PABUFLEN)-pos-1;   
1307      owl_variable_get_tostring(owl_global_get_vardict(&g), name, pos, rem);
1308      pos = buff+strlen(buff);
1309    }
1310  }
1311  rem = (buff+PABUFLEN)-pos-1;   
1312  snprintf(pos, rem, "\n");
1313  owl_variable_dict_namelist_free(&varnames);
1314 
1315  owl_function_popless_text(buff);
1316}
1317
1318void owl_function_show_variables() {
1319  owl_list varnames;
1320  owl_fmtext fm; 
1321  int i, numvarnames;
1322  char *varname;
1323
1324  owl_fmtext_init_null(&fm);
1325  owl_fmtext_append_bold(&fm, 
1326      "Variables: (use 'show variable <name>' for details)\n");
1327  owl_variable_dict_get_names(owl_global_get_vardict(&g), &varnames);
1328  numvarnames = owl_list_get_size(&varnames);
1329  for (i=0; i<numvarnames; i++) {
1330    varname = owl_list_get_element(&varnames, i);
1331    if (varname && varname[0]!='_') {
1332      owl_variable_describe(owl_global_get_vardict(&g), varname, &fm);
1333    }
1334  }
1335  owl_variable_dict_namelist_free(&varnames);
1336  owl_function_popless_fmtext(&fm);
1337  owl_fmtext_free(&fm);
1338}
1339
1340void owl_function_show_variable(char *name) {
1341  owl_fmtext fm; 
1342
1343  owl_fmtext_init_null(&fm);
1344  owl_variable_get_help(owl_global_get_vardict(&g), name, &fm);
1345  owl_function_popless_fmtext(&fm);
1346  owl_fmtext_free(&fm); 
1347}
1348
1349/* note: this applies to global message list, not to view.
1350 * If flag is 1, deletes.  If flag is 0, undeletes. */
1351void owl_function_delete_by_id(int id, int flag) {
1352  owl_messagelist *ml;
1353  owl_message *m;
1354  ml = owl_global_get_msglist(&g);
1355  m = owl_messagelist_get_by_id(ml, id);
1356  if (m) {
1357    if (flag == 1) {
1358      owl_message_mark_delete(m);
1359    } else if (flag == 0) {
1360      owl_message_unmark_delete(m);
1361    }
1362    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1363    owl_global_set_needrefresh(&g);
1364  } else {
1365    owl_function_makemsg("No message with id %d: unable to mark for (un)delete",id);
1366  }
1367}
1368
1369void owl_function_delete_automsgs() {
1370  /* mark for deletion all messages in the current view that match the
1371   * 'trash' filter */
1372
1373  int i, j, count;
1374  owl_message *m;
1375  owl_view *v;
1376  owl_filter *f;
1377
1378  /* get the trash filter */
1379  f=owl_global_get_filter(&g, "trash");
1380  if (!f) {
1381    owl_function_makemsg("No trash filter defined");
1382    return;
1383  }
1384
1385  v=owl_global_get_current_view(&g);
1386
1387  count=0;
1388  j=owl_view_get_size(v);
1389  for (i=0; i<j; i++) {
1390    m=owl_view_get_element(v, i);
1391    if (owl_filter_message_match(f, m)) {
1392      count++;
1393      owl_message_mark_delete(m);
1394    }
1395  }
1396  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1397  owl_function_makemsg("%i messages marked for deletion", count);
1398  owl_global_set_needrefresh(&g);
1399}
1400
1401
1402void owl_function_status() {
1403  char buff[5000];
1404  time_t start;
1405  int up, days, hours, minutes;
1406
1407  start=owl_global_get_starttime(&g);
1408
1409  sprintf(buff, "Version: %s\n", OWL_VERSION_STRING);
1410  sprintf(buff, "%sScreen size: %i lines, %i columns\n", buff, owl_global_get_lines(&g), owl_global_get_cols(&g));
1411  sprintf(buff, "%sStartup Arugments: %s\n", buff, owl_global_get_startupargs(&g));
1412  sprintf(buff, "%sStartup Time: %s", buff, ctime(&start));
1413
1414  up=owl_global_get_runtime(&g);
1415  days=up/86400;
1416  up-=days*86400;
1417  hours=up/3600;
1418  up-=hours*3600;
1419  minutes=up/60;
1420  up-=minutes*60;
1421  sprintf(buff, "%sRun Time: %i days %2.2i:%2.2i:%2.2i\n", buff, days, hours, minutes, up);
1422
1423  if (owl_global_get_hascolors(&g)) {
1424    sprintf(buff, "%sColor: Yes, %i color pairs.\n", buff, owl_global_get_colorpairs(&g));
1425  } else {
1426    strcat(buff, "Color: No.\n");
1427  }
1428 
1429  owl_function_popless_text(buff);
1430}
1431
1432void owl_function_show_term() {
1433  owl_fmtext fm;
1434  char buff[LINE];
1435
1436  owl_fmtext_init_null(&fm);
1437  sprintf(buff, "Terminal Lines: %i\nTerminal Columns: %i\n",
1438          owl_global_get_lines(&g),
1439          owl_global_get_cols(&g));
1440  owl_fmtext_append_normal(&fm, buff);
1441
1442  if (owl_global_get_hascolors(&g)) {
1443    owl_fmtext_append_normal(&fm, "Color: Yes\n");
1444    sprintf(buff, "Number of color pairs: %i\n", owl_global_get_colorpairs(&g));
1445    owl_fmtext_append_normal(&fm, buff);
1446    sprintf(buff, "Can change colors: %s\n", can_change_color() ? "yes" : "no");
1447    owl_fmtext_append_normal(&fm, buff);
1448  } else {
1449    owl_fmtext_append_normal(&fm, "Color: No\n");
1450  }
1451
1452  owl_function_popless_fmtext(&fm);
1453  owl_fmtext_free(&fm);
1454}
1455
1456
1457void owl_function_reply(int type, int enter) {
1458  /* if type = 0 then normal reply.
1459   * if type = 1 then it's a reply to sender
1460   * if enter = 0 then allow the command to be edited
1461   * if enter = 1 then don't wait for editing
1462   */
1463  char *buff, *oldbuff;
1464  owl_message *m;
1465  owl_filter *f;
1466 
1467  if (owl_view_get_size(owl_global_get_current_view(&g))==0) {
1468    owl_function_makemsg("No message selected");
1469  } else {
1470    char *class, *inst, *to, *cc=NULL;
1471   
1472    m=owl_view_get_element(owl_global_get_current_view(&g), owl_global_get_curmsg(&g));
1473
1474    /* first check if we catch the reply-lockout filter */
1475    f=owl_global_get_filter(&g, "reply-lockout");
1476    if (f) {
1477      if (owl_filter_message_match(f, m)) {
1478        owl_function_makemsg("Sorry, replies to this message have been disabled by the reply-lockout filter");
1479        return;
1480      }
1481    }
1482   
1483    if (owl_message_is_admin(m)) {
1484      if (owl_message_get_admintype(m)==OWL_MESSAGE_ADMINTYPE_OUTGOING) {
1485        owl_function_zwrite_setup(owl_message_get_zwriteline(m));
1486        owl_global_set_buffercommand(&g, owl_message_get_zwriteline(m));
1487      } else {
1488        owl_function_makemsg("You cannot reply to this admin message");
1489      }
1490    } else {
1491      if (owl_message_is_login(m)) {
1492        class="MESSAGE";
1493        inst="PERSONAL";
1494        to=owl_message_get_sender(m);
1495      } else if (type==1) {
1496        class="MESSAGE";
1497        inst="PERSONAL";
1498        to=owl_message_get_sender(m);
1499      } else {
1500        class=owl_message_get_class(m);
1501        inst=owl_message_get_instance(m);
1502        to=owl_message_get_recipient(m);
1503        cc=owl_message_get_cc(m);
1504        if (!strcmp(to, "") || !strcmp(to, "*")) {
1505          to="";
1506        } else if (to[0]=='@') {
1507          /* leave it, to get the realm */
1508        } else {
1509          to=owl_message_get_sender(m);
1510        }
1511      }
1512     
1513      /* create the command line */
1514      buff = owl_strdup("zwrite");
1515      if (strcasecmp(class, "message")) {
1516        buff = owl_sprintf("%s -c %s%s%s", oldbuff=buff, owl_getquoting(class), class, owl_getquoting(class));
1517        owl_free(oldbuff);
1518      }
1519      if (strcasecmp(inst, "personal")) {
1520        buff = owl_sprintf("%s -i %s%s%s", oldbuff=buff, owl_getquoting(inst), inst, owl_getquoting(inst));
1521        owl_free(oldbuff);
1522      }
1523      if (*to != '\0') {
1524        char *tmp, *oldtmp;
1525        tmp=pretty_sender(to);
1526        if (cc) {
1527          tmp = owl_util_uniq(oldtmp=tmp, cc, "-");
1528          owl_free(oldtmp);
1529          buff = owl_sprintf("%s -C %s", oldbuff=buff, tmp);
1530          owl_free(oldbuff);
1531        } else {
1532          tmp=pretty_sender(to);
1533          buff = owl_sprintf("%s %s", oldbuff=buff, tmp);
1534          owl_free(oldbuff);
1535        }
1536        owl_free(tmp);
1537      }
1538      if (cc) owl_free(cc);
1539
1540      if (enter) {
1541        owl_history *hist = owl_global_get_cmd_history(&g);
1542        owl_history_store(hist, buff);
1543        owl_history_reset(hist);
1544        owl_function_command_norv(buff);
1545      } else {
1546        owl_function_start_command(buff);
1547      }
1548      owl_free(buff);
1549    }
1550  }
1551}
1552
1553void owl_function_zlocate(char *user, int auth) {
1554  char buff[LINE], myuser[LINE];
1555  char *ptr;
1556
1557  strcpy(myuser, user);
1558  ptr=strchr(myuser, '@');
1559  if (!ptr) {
1560    strcat(myuser, "@");
1561    strcat(myuser, ZGetRealm());
1562  }
1563
1564  owl_zephyr_zlocate(myuser, buff, auth);
1565  owl_function_popless_text(buff);
1566}
1567
1568void owl_function_start_command(char *line) {
1569  int i, j;
1570  owl_editwin *tw;
1571
1572  tw=owl_global_get_typwin(&g);
1573  owl_global_set_typwin_active(&g);
1574  owl_editwin_new_style(tw, OWL_EDITWIN_STYLE_ONELINE, 
1575                        owl_global_get_cmd_history(&g));
1576
1577  owl_editwin_set_locktext(tw, "command: ");
1578  owl_global_set_needrefresh(&g);
1579
1580  j=strlen(line);
1581  for (i=0; i<j; i++) {
1582    owl_editwin_process_char(tw, line[i]);
1583  }
1584  owl_editwin_redisplay(tw, 0);
1585}
1586
1587char *owl_function_exec(int argc, char **argv, char *buff, int type) {
1588  /* if type == 1 display in a popup
1589   * if type == 2 display an admin messages
1590   * if type == 0 return output
1591   * else display in a popup
1592   */
1593  char *newbuff, *redirect = " 2>&1 < /dev/null";
1594  char *out, buff2[1024];
1595  int size;
1596  FILE *p;
1597
1598  if (argc<2) {
1599    owl_function_makemsg("Wrong number of arguments to the exec command");
1600    return NULL;
1601  }
1602
1603  buff = skiptokens(buff, 1);
1604  newbuff = owl_malloc(strlen(buff)+strlen(redirect)+1);
1605  strcpy(newbuff, buff);
1606  strcat(newbuff, redirect);
1607
1608  p=popen(newbuff, "r");
1609  out=owl_malloc(1024);
1610  size=1024;
1611  strcpy(out, "");
1612  while (fgets(buff2, 1024, p)!=NULL) {
1613    size+=1024;
1614    out=owl_realloc(out, size);
1615    strcat(out, buff2);
1616  }
1617  pclose(p);
1618
1619  if (type==1) {
1620    owl_function_popless_text(out);
1621  } else if (type==0) {
1622    return out;
1623  } else if (type==2) {
1624    owl_function_adminmsg(buff, out);
1625  } else {
1626    owl_function_popless_text(out);
1627  }
1628  owl_free(out);
1629  return NULL;
1630}
1631
1632
1633char *owl_function_perl(int argc, char **argv, char *buff, int type) {
1634  /* if type == 1 display in a popup
1635   * if type == 2 display an admin messages
1636   * if type == 0 return output
1637   * else display in a popup
1638   */
1639  char *perlout;
1640
1641  if (argc<2) {
1642    owl_function_makemsg("Wrong number of arguments to perl command");
1643    return NULL;
1644  }
1645
1646  /* consume first token (argv[0]) */
1647  buff = skiptokens(buff, 1);
1648
1649  perlout = owl_config_execute(buff);
1650  if (perlout) { 
1651    if (type==1) {
1652      owl_function_popless_text(perlout);
1653    } else if (type==2) {
1654      owl_function_adminmsg(buff, perlout);
1655    } else if (type==0) {
1656      return perlout;
1657    } else {
1658      owl_function_popless_text(perlout);
1659    }
1660    owl_free(perlout);
1661  }
1662  return NULL;
1663}
1664
1665
1666void owl_function_change_view(char *filtname) {
1667  owl_view *v;
1668  owl_filter *f;
1669  int curid=-1, newpos;
1670  owl_message *curm;
1671
1672  v=owl_global_get_current_view(&g);
1673  curm=owl_view_get_element(v, owl_global_get_curmsg(&g));
1674  if (curm) {
1675    curid = owl_message_get_id(curm);
1676    owl_view_save_curmsgid(v, curid);
1677  }
1678
1679  f=owl_global_get_filter(&g, filtname);
1680  if (!f) {
1681    owl_function_makemsg("Unknown filter");
1682    return;
1683  }
1684
1685  owl_view_free(v);
1686  owl_view_create(v, f);
1687
1688  /* Figure out where to set the current message to.
1689   * - If the previous view had messages in it, go to the closest message
1690   *   to the last message in that view.
1691   * - If the previous view was empty, attempts to restore the position
1692   *   from the last time we were in that view.  */
1693  if (curm) {
1694    newpos = owl_view_get_nearest_to_msgid(v, curid);
1695  } else {
1696    newpos = owl_view_get_nearest_to_saved(v);
1697  }
1698
1699  owl_global_set_curmsg(&g, newpos);
1700
1701  owl_global_set_curmsg_vert_offset(&g, 0);
1702  owl_global_set_direction_downwards(&g);
1703  owl_function_calculate_topmsg(OWL_DIRECTION_NONE);
1704  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1705}
1706
1707void owl_function_create_filter(int argc, char **argv) {
1708  owl_filter *f;
1709  owl_view *v;
1710  int ret, inuse=0;
1711
1712  if (argc < 2) {
1713    owl_function_makemsg("Wrong number of arguments to filter command");
1714    return;
1715  }
1716
1717  v=owl_global_get_current_view(&g);
1718
1719  /* don't touch the all filter */
1720  if (!strcmp(argv[1], "all")) {
1721    owl_function_makemsg("You may not change the 'all' filter.");
1722    return;
1723  }
1724
1725  /* deal with the case of trying change the filter color */
1726  if (argc==4 && !strcmp(argv[2], "-c")) {
1727    f=owl_global_get_filter(&g, argv[1]);
1728    if (!f) {
1729      owl_function_makemsg("The filter '%s' does not exist.", argv[1]);
1730      return;
1731    }
1732    owl_filter_set_color(f, owl_util_string_to_color(argv[3]));
1733    owl_global_set_needrefresh(&g);
1734    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1735    return;
1736  }
1737
1738  /* create the filter and check for errors */
1739  f=owl_malloc(sizeof(owl_filter));
1740  ret=owl_filter_init(f, argv[1], argc-2, argv+2);
1741  if (ret==-1) {
1742    owl_free(f);
1743    owl_function_makemsg("Invalid filter syntax");
1744    return;
1745  }
1746
1747  /* if the named filter is in use by the current view, remember it */
1748  if (!strcmp(owl_view_get_filtname(v), argv[1])) {
1749    inuse=1;
1750  }
1751
1752  /* if the named filter already exists, nuke it */
1753  if (owl_global_get_filter(&g, argv[1])) {
1754    owl_global_remove_filter(&g, argv[1]);
1755  }
1756
1757  /* add the filter */
1758  owl_global_add_filter(&g, f);
1759
1760  /* if it was in use by the current view then update */
1761  if (inuse) {
1762    owl_function_change_view(argv[1]);
1763  }
1764  owl_global_set_needrefresh(&g);
1765  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1766}
1767
1768void owl_function_show_filters() {
1769  owl_list *l;
1770  owl_filter *f;
1771  int i, j;
1772  owl_fmtext fm;
1773
1774  owl_fmtext_init_null(&fm);
1775
1776  l=owl_global_get_filterlist(&g);
1777  j=owl_list_get_size(l);
1778
1779  owl_fmtext_append_bold(&fm, "Filters:\n");
1780
1781  for (i=0; i<j; i++) {
1782    f=owl_list_get_element(l, i);
1783    owl_fmtext_append_normal(&fm, "   ");
1784    if (owl_global_get_hascolors(&g)) {
1785      owl_fmtext_append_normal_color(&fm, owl_filter_get_name(f), owl_filter_get_color(f));
1786    } else {
1787      owl_fmtext_append_normal(&fm, owl_filter_get_name(f));
1788    }
1789    owl_fmtext_append_normal(&fm, "\n");
1790  }
1791  owl_function_popless_fmtext(&fm);
1792  owl_fmtext_free(&fm);
1793}
1794
1795void owl_function_show_filter(char *name) {
1796  owl_filter *f;
1797  char buff[5000];
1798
1799  f=owl_global_get_filter(&g, name);
1800  if (!f) {
1801    owl_function_makemsg("There is no filter with that name");
1802    return;
1803  }
1804  owl_filter_print(f, buff);
1805  owl_function_popless_text(buff);
1806}
1807
1808void owl_function_show_zpunts() {
1809  owl_filter *f;
1810  owl_list *fl;
1811  char buff[5000];
1812  owl_fmtext fm;
1813  int i, j;
1814
1815  owl_fmtext_init_null(&fm);
1816
1817  fl=owl_global_get_puntlist(&g);
1818  j=owl_list_get_size(fl);
1819  owl_fmtext_append_bold(&fm, "Active zpunt filters:\n");
1820
1821  for (i=0; i<j; i++) {
1822    f=owl_list_get_element(fl, i);
1823    owl_filter_print(f, buff);
1824    owl_fmtext_append_normal(&fm, buff);
1825  }
1826  owl_function_popless_fmtext(&fm);
1827  owl_fmtext_free(&fm);
1828}
1829
1830char *owl_function_fastclassinstfilt(char *class, char *instance) {
1831  /* creates a filter for a class, instance if one doesn't exist.
1832   * If instance is null then apply for all messgaes in the class.
1833   * returns the name of the filter, which the caller must free.*/
1834  owl_list *fl;
1835  owl_filter *f;
1836  char *argbuff, *filtname;
1837  int len;
1838
1839  fl=owl_global_get_filterlist(&g);
1840
1841  /* name for the filter */
1842  len=strlen(class)+30;
1843  if (instance) len+=strlen(instance);
1844  filtname=owl_malloc(len);
1845  if (!instance) {
1846    sprintf(filtname, "class-%s", class);
1847  } else {
1848    sprintf(filtname, "class-%s-instance-%s", class, instance);
1849  }
1850  downstr(filtname);
1851
1852  /* if it already exists then go with it.  This lets users override */
1853  if (owl_global_get_filter(&g, filtname)) {
1854    return filtname;
1855  }
1856
1857  /* create the new filter */
1858  argbuff=owl_malloc(len+20);
1859  sprintf(argbuff, "( class ^%s$ )", class);
1860  if (instance) {
1861    sprintf(argbuff, "%s and ( instance ^%s$ )", argbuff, instance);
1862  }
1863
1864  f=owl_malloc(sizeof(owl_filter));
1865  owl_filter_init_fromstring(f, filtname, argbuff);
1866
1867  /* add it to the global list */
1868  owl_global_add_filter(&g, f);
1869
1870  owl_free(argbuff);
1871  return filtname;
1872}
1873
1874char *owl_function_fastuserfilt(char *user) {
1875  owl_filter *f;
1876  char *argbuff, *longuser, *shortuser, *filtname;
1877
1878  /* stick the local realm on if it's not there */
1879  longuser=long_sender(user);
1880  shortuser=pretty_sender(user);
1881
1882  /* name for the filter */
1883  filtname=owl_malloc(strlen(shortuser)+20);
1884  sprintf(filtname, "user-%s", shortuser);
1885
1886  /* if it already exists then go with it.  This lets users override */
1887  if (owl_global_get_filter(&g, filtname)) {
1888    return filtname;
1889  }
1890
1891  /* create the new-internal filter */
1892  f=owl_malloc(sizeof(owl_filter));
1893
1894  argbuff=owl_malloc(strlen(longuser)+200);
1895  sprintf(argbuff, "( ( class ^message$ ) and ( instance ^personal$ ) and ( sender ^%s$ ) )", longuser);
1896  sprintf(argbuff, "%s or ( ( type ^admin$ ) and ( recipient %s ) )", argbuff, shortuser);
1897  sprintf(argbuff, "%s or ( ( class ^login$ ) and ( sender ^%s$ ) )", argbuff, longuser);
1898
1899  owl_filter_init_fromstring(f, filtname, argbuff);
1900
1901  /* add it to the global list */
1902  owl_global_add_filter(&g, f);
1903
1904  /* free stuff */
1905  owl_free(argbuff);
1906  owl_free(longuser);
1907  owl_free(shortuser);
1908
1909  return filtname;
1910}
1911
1912char *owl_function_fasttypefilt(char *type) {
1913  owl_filter *f;
1914  char *argbuff, *filtname;
1915
1916  /* name for the filter */
1917  filtname=owl_sprintf("type-%s", type);
1918
1919  /* if it already exists then go with it.  This lets users override */
1920  if (owl_global_get_filter(&g, filtname)) {
1921    return filtname;
1922  }
1923
1924  /* create the new-internal filter */
1925  f=owl_malloc(sizeof(owl_filter));
1926
1927  argbuff = owl_sprintf("type ^%s$", type);
1928
1929  owl_filter_init_fromstring(f, filtname, argbuff);
1930
1931  /* add it to the global list */
1932  owl_global_add_filter(&g, f);
1933
1934  /* free stuff */
1935  owl_free(argbuff);
1936
1937  return filtname;
1938}
1939
1940/* If flag is 1, marks for deletion.  If flag is 0,
1941 * unmarks for deletion. */
1942void owl_function_delete_curview_msgs(int flag) {
1943  owl_view *v;
1944  int i, j;
1945
1946  v=owl_global_get_current_view(&g);
1947  j=owl_view_get_size(v);
1948  for (i=0; i<j; i++) {
1949    if (flag == 1) {
1950      owl_message_mark_delete(owl_view_get_element(v, i));
1951    } else if (flag == 0) {
1952      owl_message_unmark_delete(owl_view_get_element(v, i));
1953    }
1954  }
1955
1956  owl_function_makemsg("%i messages marked for %sdeletion", j, flag?"":"un");
1957
1958  owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 
1959}
1960
1961char *owl_function_smartfilter(int type) {
1962  /* Returns the name of a filter, or null.  The caller
1963   * must free this name.  */
1964  /* if the curmsg is a personal message return a filter name
1965   *    to the converstaion with that user.
1966   * If the curmsg is a class message, instance foo, recip *
1967   *    message, return a filter name to the class, inst.
1968   * If the curmsg is a class message and type==0 then
1969   *    return a filter name for just the class.
1970   * If the curmsg is a class message and type==1 then
1971   *    return a filter name for the class and instance.
1972   */
1973  owl_view *v;
1974  owl_message *m;
1975  char *sender, *filtname=NULL;
1976 
1977  v=owl_global_get_current_view(&g);
1978  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
1979
1980  if (owl_view_get_size(v)==0) {
1981    owl_function_makemsg("No message selected\n");
1982    return NULL;
1983  }
1984
1985  /* very simple handling of admin messages for now */
1986  if (owl_message_is_admin(m)) {
1987    return owl_function_fasttypefilt("admin");
1988  }
1989
1990  /* narrow personal and login messages to the sender */
1991  if (owl_message_is_personal(m) || owl_message_is_login(m)) {
1992    if (owl_message_is_zephyr(m)) {
1993      sender=pretty_sender(owl_message_get_sender(m));
1994      filtname = owl_function_fastuserfilt(sender);
1995      owl_free(sender);
1996      return filtname;
1997    }
1998    return NULL;
1999  }
2000
2001  /* narrow class MESSAGE, instance foo, recip * messages to class, inst */
2002  if (!strcasecmp(owl_message_get_class(m), "message") &&
2003      !owl_message_is_personal(m)) {
2004    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
2005    return filtname;
2006  }
2007
2008  /* otherwise narrow to the class */
2009  if (type==0) {
2010    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), NULL);
2011  } else if (type==1) {
2012    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
2013  }
2014  return filtname;
2015}
2016
2017void owl_function_smartzpunt(int type) {
2018  /* Starts a zpunt command based on the current class,instance pair.
2019   * If type=0, uses just class.  If type=1, uses instance as well. */
2020  owl_view *v;
2021  owl_message *m;
2022  char *cmd, *cmdprefix, *mclass, *minst;
2023 
2024  v=owl_global_get_current_view(&g);
2025  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
2026
2027  if (owl_view_get_size(v)==0) {
2028    owl_function_makemsg("No message selected\n");
2029    return;
2030  }
2031
2032  /* for now we skip admin messages. */
2033  if (owl_message_is_admin(m)
2034      || owl_message_is_login(m)
2035      || !owl_message_is_zephyr(m)) {
2036    owl_function_makemsg("smartzpunt doesn't support this message type.");
2037    return;
2038  }
2039
2040  mclass = owl_message_get_class(m);
2041  minst = owl_message_get_instance(m);
2042  if (!mclass || !*mclass || *mclass==' '
2043      || (!strcasecmp(mclass, "message") && !strcasecmp(minst, "personal"))
2044      || (type && (!minst || !*minst|| *minst==' '))) {
2045    owl_function_makemsg("smartzpunt can't safely do this for <%s,%s>",
2046                         mclass, minst);
2047  } else {
2048    cmdprefix = "start-command zpunt ";
2049    cmd = owl_malloc(strlen(cmdprefix)+strlen(mclass)+strlen(minst)+3);
2050    strcpy(cmd, cmdprefix);
2051    strcat(cmd, mclass);
2052    if (type) {
2053      strcat(cmd, " ");
2054      strcat(cmd, minst);
2055    } else {
2056      strcat(cmd, " *");
2057    }
2058    owl_function_command(cmd);
2059    owl_free(cmd);
2060  }
2061}
2062
2063
2064
2065void owl_function_color_current_filter(char *color) {
2066  owl_filter *f;
2067  char *name;
2068
2069  name=owl_view_get_filtname(owl_global_get_current_view(&g));
2070  f=owl_global_get_filter(&g, name);
2071  if (!f) {
2072    owl_function_makemsg("Unknown filter");
2073    return;
2074  }
2075
2076  /* don't touch the all filter */
2077  if (!strcmp(name, "all")) {
2078    owl_function_makemsg("You may not change the 'all' filter.");
2079    return;
2080  }
2081
2082  /* deal with the case of trying change the filter color */
2083  owl_filter_set_color(f, owl_util_string_to_color(color));
2084  owl_global_set_needrefresh(&g);
2085  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2086}
2087
2088void owl_function_show_colors() {
2089  owl_fmtext fm;
2090
2091  owl_fmtext_init_null(&fm);
2092  owl_fmtext_append_normal_color(&fm, "default\n", OWL_COLOR_DEFAULT);
2093  owl_fmtext_append_normal_color(&fm, "red\n", OWL_COLOR_RED);
2094  owl_fmtext_append_normal_color(&fm, "green\n", OWL_COLOR_GREEN);
2095  owl_fmtext_append_normal_color(&fm, "yellow\n", OWL_COLOR_YELLOW);
2096  owl_fmtext_append_normal_color(&fm, "blue\n", OWL_COLOR_BLUE);
2097  owl_fmtext_append_normal_color(&fm, "magenta\n", OWL_COLOR_MAGENTA);
2098  owl_fmtext_append_normal_color(&fm, "cyan\n", OWL_COLOR_CYAN);
2099  owl_fmtext_append_normal_color(&fm, "white\n", OWL_COLOR_WHITE);
2100
2101  owl_function_popless_fmtext(&fm);
2102  owl_fmtext_free(&fm);
2103}
2104
2105void owl_function_zpunt(char *class, char *inst, char *recip, int direction) {
2106  /* add the given class, inst, recip to the punt list for filtering.
2107   *   if direction==0 then punt
2108   *   if direction==1 then unpunt */
2109  owl_filter *f;
2110  owl_list *fl;
2111  char *buff;
2112  int ret, i, j;
2113
2114  fl=owl_global_get_puntlist(&g);
2115
2116  /* first, create the filter */
2117  f=malloc(sizeof(owl_filter));
2118  buff=malloc(strlen(class)+strlen(inst)+strlen(recip)+100);
2119  if (!strcmp(recip, "*")) {
2120    sprintf(buff, "class ^%s$ and instance ^%s$", class, inst);
2121  } else {
2122    sprintf(buff, "class ^%s$ and instance ^%s$ and recipient %s", class, inst, recip);
2123  }
2124  owl_function_debugmsg("About to filter %s", buff);
2125  ret=owl_filter_init_fromstring(f, "punt-filter", buff);
2126  owl_free(buff);
2127  if (ret) {
2128    owl_function_makemsg("Error creating filter for zpunt");
2129    owl_filter_free(f);
2130    return;
2131  }
2132
2133  /* Check for an identical filter */
2134  j=owl_list_get_size(fl);
2135  for (i=0; i<j; i++) {
2136    if (owl_filter_equiv(f, owl_list_get_element(fl, i))) {
2137      /* if we're punting, then just silently bow out on this duplicate */
2138      if (direction==0) {
2139        owl_filter_free(f);
2140        return;
2141      }
2142
2143      /* if we're unpunting, then remove this filter from the puntlist */
2144      if (direction==1) {
2145        owl_filter_free(owl_list_get_element(fl, i));
2146        owl_list_remove_element(fl, i);
2147        return;
2148      }
2149    }
2150  }
2151
2152  /* If we're punting, add the filter to the global punt list */
2153  if (direction==0) {
2154    owl_list_append_element(fl, f);
2155  }
2156}
2157
2158void owl_function_activate_keymap(char *keymap) {
2159  if (!owl_keyhandler_activate(owl_global_get_keyhandler(&g), keymap)) {
2160    owl_function_makemsg("Unable to activate keymap '%s'", keymap);
2161  }
2162}
2163
2164
2165void owl_function_show_keymaps() {
2166  owl_list l;
2167  owl_fmtext fm;
2168  owl_keymap *km;
2169  owl_keyhandler *kh;
2170  int i, numkm;
2171  char *kmname;
2172
2173  kh = owl_global_get_keyhandler(&g);
2174  owl_fmtext_init_null(&fm);
2175  owl_fmtext_append_bold(&fm, "Keymaps:   ");
2176  owl_fmtext_append_normal(&fm, "(use 'show keymap <name>' for details)\n");
2177  owl_keyhandler_get_keymap_names(kh, &l);
2178  owl_fmtext_append_list(&fm, &l, "\n", owl_function_keymap_summary);
2179  owl_fmtext_append_normal(&fm, "\n");
2180
2181  numkm = owl_list_get_size(&l);
2182  for (i=0; i<numkm; i++) {
2183    kmname = owl_list_get_element(&l, i);
2184    km = owl_keyhandler_get_keymap(kh, kmname);
2185    owl_fmtext_append_bold(&fm, "\n\n----------------------------------------------------------------------------------------------------\n\n");
2186    owl_keymap_get_details(km, &fm);   
2187  }
2188  owl_fmtext_append_normal(&fm, "\n");
2189 
2190  owl_function_popless_fmtext(&fm);
2191  owl_keyhandler_keymap_namelist_free(&l);
2192  owl_fmtext_free(&fm);
2193}
2194
2195char *owl_function_keymap_summary(void *name) {
2196  owl_keymap *km
2197    = owl_keyhandler_get_keymap(owl_global_get_keyhandler(&g), name);
2198  if (km) return owl_keymap_summary(km);
2199  else return(NULL);
2200}
2201
2202/* TODO: implement for real */
2203void owl_function_show_keymap(char *name) {
2204  owl_fmtext fm;
2205  owl_keymap *km;
2206
2207  owl_fmtext_init_null(&fm);
2208  km = owl_keyhandler_get_keymap(owl_global_get_keyhandler(&g), name);
2209  if (km) {
2210    owl_keymap_get_details(km, &fm);
2211  } else {
2212    owl_fmtext_append_normal(&fm, "No such keymap...\n");
2213  } 
2214  owl_function_popless_fmtext(&fm);
2215  owl_fmtext_free(&fm);
2216}
2217
2218
2219void owl_function_help_for_command(char *cmdname) {
2220  owl_fmtext fm;
2221
2222  owl_fmtext_init_null(&fm);
2223  owl_cmd_get_help(owl_global_get_cmddict(&g), cmdname, &fm);
2224  owl_function_popless_fmtext(&fm); 
2225  owl_fmtext_free(&fm);
2226}
2227
2228void owl_function_search_start(char *string, int direction) {
2229  /* direction is OWL_DIRECTION_DOWNWARDS or OWL_DIRECTION_UPWARDS */
2230  owl_global_set_search_active(&g, string);
2231  owl_function_search_helper(0, direction);
2232}
2233
2234void owl_function_search_continue(int direction) {
2235  /* direction is OWL_DIRECTION_DOWNWARDS or OWL_DIRECTION_UPWARDS */
2236  owl_function_search_helper(1, direction);
2237}
2238
2239void owl_function_search_helper(int mode, int direction) {
2240  /* move to a message that contains the string.  If direction is
2241   * OWL_DIRECTION_DOWNWARDS then search fowards, if direction is
2242   * OWL_DIRECTION_UPWARDS then search backwards.
2243   *
2244   * If mode==0 then it will stay on the current message if it
2245   * contains the string.
2246   */
2247
2248  owl_view *v;
2249  int viewsize, i, curmsg, start;
2250  owl_message *m;
2251
2252  v=owl_global_get_current_view(&g);
2253  viewsize=owl_view_get_size(v);
2254  curmsg=owl_global_get_curmsg(&g);
2255 
2256  if (viewsize==0) {
2257    owl_function_makemsg("No messages present");
2258    return;
2259  }
2260
2261  if (mode==0) {
2262    start=curmsg;
2263  } else if (direction==OWL_DIRECTION_DOWNWARDS) {
2264    start=curmsg+1;
2265  } else {
2266    start=curmsg-1;
2267  }
2268
2269  /* bounds check */
2270  if (start>=viewsize || start<0) {
2271    owl_function_makemsg("No further matches found");
2272    return;
2273  }
2274
2275  for (i=start; i<viewsize && i>=0;) {
2276    m=owl_view_get_element(v, i);
2277    if (owl_message_search(m, owl_global_get_search_string(&g))) {
2278      owl_global_set_curmsg(&g, i);
2279      owl_function_calculate_topmsg(direction);
2280      owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2281      if (direction==OWL_DIRECTION_DOWNWARDS) {
2282        owl_global_set_direction_downwards(&g);
2283      } else {
2284        owl_global_set_direction_upwards(&g);
2285      }
2286      return;
2287    }
2288    if (direction==OWL_DIRECTION_DOWNWARDS) {
2289      i++;
2290    } else {
2291      i--;
2292    }
2293  }
2294  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2295  owl_function_makemsg("No matches found");
2296}
2297
2298
2299/* strips formatting from ztext and returns the unformatted text.
2300 * caller is responsible for freeing. */
2301char *owl_function_ztext_stylestrip(char *zt) {
2302  owl_fmtext fm;
2303  char *plaintext;
2304
2305  owl_fmtext_init_null(&fm);
2306  owl_fmtext_append_ztext(&fm, zt);
2307  plaintext = owl_fmtext_print_plain(&fm);
2308  owl_fmtext_free(&fm);
2309  return(plaintext);
2310}
Note: See TracBrowser for help on using the repository browser.