source: functions.c @ aa2f33b3

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since aa2f33b3 was aa2f33b3, checked in by Erik Nygren <nygren@mit.edu>, 22 years ago
Variables now have a summary and a long description. Only the summary is shown with help. The long description is shown with "show variable foo". Fix the scrolling bug where we would sometimes fail to scroll the screen down, leaving the current message off the bottom of the screen. Added a 'scrollmode' variable which determines how the screen will scroll as the cursor moves. The default behaves identically to previous versions of owl. The following modes are supported: normal - This is the owl default. Scrolling happens when it needs to, and an attempt is made to keep the current message roughly near the middle of the screen. (default) top - The current message will always be the the top message displayed. neartop - The current message will be one down from the top message displayed, where possible. center - An attempt is made to keep the current message near the center of the screen. paged - The top message displayed only changes when user moves the cursor to the top or bottom of the screen. When it moves, the screen will be paged up or down and the cursor will be near the top or the bottom. pagedcenter - The top message displayed only changes when user moves the cursor to the top or bottom of the screen. When it moves, the screen will be paged up or down and the cursor will be near the center.
  • Property mode set to 100644
File size: 57.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
1249  owl_global_set_curmsg(&g, i);
1250  owl_function_nextmsg();
1251}
1252
1253void owl_function_mainwin_pageup() {
1254  owl_global_set_curmsg(&g, owl_global_get_topmsg(&g));
1255  owl_function_prevmsg();
1256}
1257
1258void owl_function_getsubs() {
1259  int ret, num, i, one;
1260  ZSubscription_t sub;
1261  char *buff;
1262
1263  one = 1;
1264
1265  ret=ZRetrieveSubscriptions(0, &num);
1266  if (ret == ZERR_TOOMANYSUBS) {
1267
1268  }
1269
1270  buff=owl_malloc(num*200);
1271  strcpy(buff, "");
1272  for (i=0; i<num; i++) {
1273    if ((ret = ZGetSubscriptions(&sub, &one)) != ZERR_NONE) {
1274      /* deal with error */
1275    } else {
1276      sprintf(buff, "%s<%s,%s,%s>\n", buff, sub.zsub_class, sub.zsub_classinst, sub.zsub_recipient);
1277    }
1278  }
1279
1280  owl_function_popless_text(buff);
1281  owl_free(buff);
1282  ZFlushSubscriptions();
1283}
1284
1285#define PABUFLEN 5000
1286void owl_function_printallvars() {
1287  char buff[PABUFLEN], *pos, *name;
1288  owl_list varnames;
1289  int i, numvarnames, rem;
1290
1291  pos = buff;
1292  pos += sprintf(pos, "%-20s = %s\n", "VARIABLE", "VALUE");
1293  pos += sprintf(pos, "%-20s   %s\n",  "--------", "-----");
1294  owl_variable_dict_get_names(owl_global_get_vardict(&g), &varnames);
1295  rem = (buff+PABUFLEN)-pos-1;
1296  numvarnames = owl_list_get_size(&varnames);
1297  for (i=0; i<numvarnames; i++) {
1298    name = owl_list_get_element(&varnames, i);
1299    if (name && name[0]!='_') {
1300      rem = (buff+PABUFLEN)-pos-1;   
1301      pos += snprintf(pos, rem, "\n%-20s = ", name);
1302      rem = (buff+PABUFLEN)-pos-1;   
1303      owl_variable_get_tostring(owl_global_get_vardict(&g), name, pos, rem);
1304      pos = buff+strlen(buff);
1305    }
1306  }
1307  rem = (buff+PABUFLEN)-pos-1;   
1308  snprintf(pos, rem, "\n");
1309  owl_variable_dict_namelist_free(&varnames);
1310 
1311  owl_function_popless_text(buff);
1312}
1313
1314void owl_function_show_variables() {
1315  owl_list varnames;
1316  owl_fmtext fm; 
1317  int i, numvarnames;
1318  char *varname;
1319
1320  owl_fmtext_init_null(&fm);
1321  owl_fmtext_append_bold(&fm, 
1322      "Variables: (use 'show variable <name>' for details)\n");
1323  owl_variable_dict_get_names(owl_global_get_vardict(&g), &varnames);
1324  numvarnames = owl_list_get_size(&varnames);
1325  for (i=0; i<numvarnames; i++) {
1326    varname = owl_list_get_element(&varnames, i);
1327    if (varname && varname[0]!='_') {
1328      owl_variable_describe(owl_global_get_vardict(&g), varname, &fm);
1329    }
1330  }
1331  owl_variable_dict_namelist_free(&varnames);
1332  owl_function_popless_fmtext(&fm);
1333  owl_fmtext_free(&fm);
1334}
1335
1336void owl_function_show_variable(char *name) {
1337  owl_fmtext fm; 
1338
1339  owl_fmtext_init_null(&fm);
1340  owl_variable_get_help(owl_global_get_vardict(&g), name, &fm);
1341  owl_function_popless_fmtext(&fm);
1342  owl_fmtext_free(&fm); 
1343}
1344
1345/* note: this applies to global message list, not to view.
1346 * If flag is 1, deletes.  If flag is 0, undeletes. */
1347void owl_function_delete_by_id(int id, int flag) {
1348  owl_messagelist *ml;
1349  owl_message *m;
1350  ml = owl_global_get_msglist(&g);
1351  m = owl_messagelist_get_by_id(ml, id);
1352  if (m) {
1353    if (flag == 1) {
1354      owl_message_mark_delete(m);
1355    } else if (flag == 0) {
1356      owl_message_unmark_delete(m);
1357    }
1358    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1359    owl_global_set_needrefresh(&g);
1360  } else {
1361    owl_function_makemsg("No message with id %d: unable to mark for (un)delete",id);
1362  }
1363}
1364
1365void owl_function_delete_automsgs() {
1366  /* mark for deletion all messages in the current view that match the
1367   * 'trash' filter */
1368
1369  int i, j, count;
1370  owl_message *m;
1371  owl_view *v;
1372  owl_filter *f;
1373
1374  /* get the trash filter */
1375  f=owl_global_get_filter(&g, "trash");
1376  if (!f) {
1377    owl_function_makemsg("No trash filter defined");
1378    return;
1379  }
1380
1381  v=owl_global_get_current_view(&g);
1382
1383  count=0;
1384  j=owl_view_get_size(v);
1385  for (i=0; i<j; i++) {
1386    m=owl_view_get_element(v, i);
1387    if (owl_filter_message_match(f, m)) {
1388      count++;
1389      owl_message_mark_delete(m);
1390    }
1391  }
1392  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1393  owl_function_makemsg("%i messages marked for deletion", count);
1394  owl_global_set_needrefresh(&g);
1395}
1396
1397
1398void owl_function_status() {
1399  char buff[5000];
1400  time_t start;
1401  int up, days, hours, minutes;
1402
1403  start=owl_global_get_starttime(&g);
1404
1405  sprintf(buff, "Version: %s\n", OWL_VERSION_STRING);
1406  sprintf(buff, "%sScreen size: %i lines, %i columns\n", buff, owl_global_get_lines(&g), owl_global_get_cols(&g));
1407  sprintf(buff, "%sStartup Arugments: %s\n", buff, owl_global_get_startupargs(&g));
1408  sprintf(buff, "%sStartup Time: %s", buff, ctime(&start));
1409
1410  up=owl_global_get_runtime(&g);
1411  days=up/86400;
1412  up-=days*86400;
1413  hours=up/3600;
1414  up-=hours*3600;
1415  minutes=up/60;
1416  up-=minutes*60;
1417  sprintf(buff, "%sRun Time: %i days %2.2i:%2.2i:%2.2i\n", buff, days, hours, minutes, up);
1418
1419  if (owl_global_get_hascolors(&g)) {
1420    sprintf(buff, "%sColor: Yes, %i color pairs.\n", buff, owl_global_get_colorpairs(&g));
1421  } else {
1422    strcat(buff, "Color: No.\n");
1423  }
1424 
1425  owl_function_popless_text(buff);
1426}
1427
1428void owl_function_show_term() {
1429  owl_fmtext fm;
1430  char buff[LINE];
1431
1432  owl_fmtext_init_null(&fm);
1433  sprintf(buff, "Terminal Lines: %i\nTerminal Columns: %i\n",
1434          owl_global_get_lines(&g),
1435          owl_global_get_cols(&g));
1436  owl_fmtext_append_normal(&fm, buff);
1437
1438  if (owl_global_get_hascolors(&g)) {
1439    owl_fmtext_append_normal(&fm, "Color: Yes\n");
1440    sprintf(buff, "Number of color pairs: %i\n", owl_global_get_colorpairs(&g));
1441    owl_fmtext_append_normal(&fm, buff);
1442    sprintf(buff, "Can change colors: %s\n", can_change_color() ? "yes" : "no");
1443    owl_fmtext_append_normal(&fm, buff);
1444  } else {
1445    owl_fmtext_append_normal(&fm, "Color: No\n");
1446  }
1447
1448  owl_function_popless_fmtext(&fm);
1449  owl_fmtext_free(&fm);
1450}
1451
1452
1453void owl_function_reply(int type, int enter) {
1454  /* if type = 0 then normal reply.
1455   * if type = 1 then it's a reply to sender
1456   * if enter = 0 then allow the command to be edited
1457   * if enter = 1 then don't wait for editing
1458   */
1459  char *buff, *oldbuff;
1460  owl_message *m;
1461  owl_filter *f;
1462 
1463  if (owl_view_get_size(owl_global_get_current_view(&g))==0) {
1464    owl_function_makemsg("No message selected");
1465  } else {
1466    char *class, *inst, *to, *cc=NULL;
1467   
1468    m=owl_view_get_element(owl_global_get_current_view(&g), owl_global_get_curmsg(&g));
1469
1470    /* first check if we catch the reply-lockout filter */
1471    f=owl_global_get_filter(&g, "reply-lockout");
1472    if (f) {
1473      if (owl_filter_message_match(f, m)) {
1474        owl_function_makemsg("Sorry, replies to this message have been disabled by the reply-lockout filter");
1475        return;
1476      }
1477    }
1478   
1479    if (owl_message_is_admin(m)) {
1480      if (owl_message_get_admintype(m)==OWL_MESSAGE_ADMINTYPE_OUTGOING) {
1481        owl_function_zwrite_setup(owl_message_get_zwriteline(m));
1482        owl_global_set_buffercommand(&g, owl_message_get_zwriteline(m));
1483      } else {
1484        owl_function_makemsg("You cannot reply to this admin message");
1485      }
1486    } else {
1487      if (owl_message_is_login(m)) {
1488        class="MESSAGE";
1489        inst="PERSONAL";
1490        to=owl_message_get_sender(m);
1491      } else if (type==1) {
1492        class="MESSAGE";
1493        inst="PERSONAL";
1494        to=owl_message_get_sender(m);
1495      } else {
1496        class=owl_message_get_class(m);
1497        inst=owl_message_get_instance(m);
1498        to=owl_message_get_recipient(m);
1499        cc=owl_message_get_cc(m);
1500        if (!strcmp(to, "") || !strcmp(to, "*")) {
1501          to="";
1502        } else if (to[0]=='@') {
1503          /* leave it, to get the realm */
1504        } else {
1505          to=owl_message_get_sender(m);
1506        }
1507      }
1508     
1509      /* create the command line */
1510      buff = owl_strdup("zwrite");
1511      if (strcasecmp(class, "message")) {
1512        buff = owl_sprintf("%s -c %s%s%s", oldbuff=buff, owl_getquoting(class), class, owl_getquoting(class));
1513        owl_free(oldbuff);
1514      }
1515      if (strcasecmp(inst, "personal")) {
1516        buff = owl_sprintf("%s -i %s%s%s", oldbuff=buff, owl_getquoting(inst), inst, owl_getquoting(inst));
1517        owl_free(oldbuff);
1518      }
1519      if (*to != '\0') {
1520        char *tmp, *oldtmp;
1521        tmp=pretty_sender(to);
1522        if (cc) {
1523          tmp = owl_util_uniq(oldtmp=tmp, cc, "-");
1524          owl_free(oldtmp);
1525          buff = owl_sprintf("%s -C %s", oldbuff=buff, tmp);
1526          owl_free(oldbuff);
1527        } else {
1528          tmp=pretty_sender(to);
1529          buff = owl_sprintf("%s %s", oldbuff=buff, tmp);
1530          owl_free(oldbuff);
1531        }
1532        owl_free(tmp);
1533      }
1534      if (cc) owl_free(cc);
1535
1536      if (enter) {
1537        owl_history *hist = owl_global_get_cmd_history(&g);
1538        owl_history_store(hist, buff);
1539        owl_history_reset(hist);
1540        owl_function_command_norv(buff);
1541      } else {
1542        owl_function_start_command(buff);
1543      }
1544      owl_free(buff);
1545    }
1546  }
1547}
1548
1549void owl_function_zlocate(char *user, int auth) {
1550  char buff[LINE], myuser[LINE];
1551  char *ptr;
1552
1553  strcpy(myuser, user);
1554  ptr=strchr(myuser, '@');
1555  if (!ptr) {
1556    strcat(myuser, "@");
1557    strcat(myuser, ZGetRealm());
1558  }
1559
1560  owl_zephyr_zlocate(myuser, buff, auth);
1561  owl_function_popless_text(buff);
1562}
1563
1564void owl_function_start_command(char *line) {
1565  int i, j;
1566  owl_editwin *tw;
1567
1568  tw=owl_global_get_typwin(&g);
1569  owl_global_set_typwin_active(&g);
1570  owl_editwin_new_style(tw, OWL_EDITWIN_STYLE_ONELINE, 
1571                        owl_global_get_cmd_history(&g));
1572
1573  owl_editwin_set_locktext(tw, "command: ");
1574  owl_global_set_needrefresh(&g);
1575
1576  j=strlen(line);
1577  for (i=0; i<j; i++) {
1578    owl_editwin_process_char(tw, line[i]);
1579  }
1580  owl_editwin_redisplay(tw, 0);
1581}
1582
1583char *owl_function_exec(int argc, char **argv, char *buff, int type) {
1584  /* if type == 1 display in a popup
1585   * if type == 2 display an admin messages
1586   * if type == 0 return output
1587   * else display in a popup
1588   */
1589  char *newbuff, *redirect = " 2>&1 < /dev/null";
1590  char *out, buff2[1024];
1591  int size;
1592  FILE *p;
1593
1594  if (argc<2) {
1595    owl_function_makemsg("Wrong number of arguments to the pexec command");
1596    return NULL;
1597  }
1598
1599  buff = skiptokens(buff, 1);
1600  newbuff = owl_malloc(strlen(buff)+strlen(redirect)+1);
1601  strcpy(newbuff, buff);
1602  strcat(newbuff, redirect);
1603
1604  p=popen(newbuff, "r");
1605  out=owl_malloc(1024);
1606  size=1024;
1607  strcpy(out, "");
1608  while (fgets(buff2, 1024, p)!=NULL) {
1609    size+=1024;
1610    out=owl_realloc(out, size);
1611    strcat(out, buff2);
1612  }
1613  pclose(p);
1614
1615  if (type==1) {
1616    owl_function_popless_text(out);
1617  } else if (type==0) {
1618    return out;
1619  } else if (type==2) {
1620    owl_function_adminmsg(buff, out);
1621  } else {
1622    owl_function_popless_text(out);
1623  }
1624  owl_free(out);
1625  return NULL;
1626}
1627
1628
1629char *owl_function_perl(int argc, char **argv, char *buff, int type) {
1630  /* if type == 1 display in a popup
1631   * if type == 2 display an admin messages
1632   * if type == 0 return output
1633   * else display in a popup
1634   */
1635  char *perlout;
1636
1637  if (argc<2) {
1638    owl_function_makemsg("Wrong number of arguments to perl command");
1639    return NULL;
1640  }
1641
1642  /* consume first token (argv[0]) */
1643  buff = skiptokens(buff, 1);
1644
1645  perlout = owl_config_execute(buff);
1646  if (perlout) { 
1647    if (type==1) {
1648      owl_function_popless_text(perlout);
1649    } else if (type==2) {
1650      owl_function_adminmsg(buff, perlout);
1651    } else if (type==0) {
1652      return perlout;
1653    } else {
1654      owl_function_popless_text(perlout);
1655    }
1656    owl_free(perlout);
1657  }
1658  return NULL;
1659}
1660
1661
1662void owl_function_change_view(char *filtname) {
1663  owl_view *v;
1664  owl_filter *f;
1665
1666  v=owl_global_get_current_view(&g);
1667  f=owl_global_get_filter(&g, filtname);
1668  if (!f) {
1669    owl_function_makemsg("Unknown filter");
1670    return;
1671  }
1672
1673  owl_view_free(v);
1674  owl_view_create(v, f);
1675
1676  owl_global_set_curmsg(&g, 0);
1677  owl_global_set_curmsg_vert_offset(&g, 0);
1678  owl_global_set_direction_downwards(&g);
1679  owl_function_calculate_topmsg(OWL_DIRECTION_NONE);
1680  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1681}
1682
1683void owl_function_create_filter(int argc, char **argv) {
1684  owl_filter *f;
1685  owl_view *v;
1686  int ret, inuse=0;
1687
1688  if (argc < 2) {
1689    owl_function_makemsg("Wrong number of arguments to filter command");
1690    return;
1691  }
1692
1693  v=owl_global_get_current_view(&g);
1694
1695  /* don't touch the all filter */
1696  if (!strcmp(argv[1], "all")) {
1697    owl_function_makemsg("You may not change the 'all' filter.");
1698    return;
1699  }
1700
1701  /* deal with the case of trying change the filter color */
1702  if (argc==4 && !strcmp(argv[2], "-c")) {
1703    f=owl_global_get_filter(&g, argv[1]);
1704    if (!f) {
1705      owl_function_makemsg("The filter '%s' does not exist.", argv[1]);
1706      return;
1707    }
1708    owl_filter_set_color(f, owl_util_string_to_color(argv[3]));
1709    owl_global_set_needrefresh(&g);
1710    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1711    return;
1712  }
1713
1714  /* create the filter and check for errors */
1715  f=owl_malloc(sizeof(owl_filter));
1716  ret=owl_filter_init(f, argv[1], argc-2, argv+2);
1717  if (ret==-1) {
1718    owl_free(f);
1719    owl_function_makemsg("Invalid filter syntax");
1720    return;
1721  }
1722
1723  /* if the named filter is in use by the current view, remember it */
1724  if (!strcmp(owl_view_get_filtname(v), argv[1])) {
1725    inuse=1;
1726  }
1727
1728  /* if the named filter already exists, nuke it */
1729  if (owl_global_get_filter(&g, argv[1])) {
1730    owl_global_remove_filter(&g, argv[1]);
1731  }
1732
1733  /* add the filter */
1734  owl_global_add_filter(&g, f);
1735
1736  /* if it was in use by the current view then update */
1737  if (inuse) {
1738    owl_function_change_view(argv[1]);
1739  }
1740  owl_global_set_needrefresh(&g);
1741  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1742}
1743
1744void owl_function_show_filters() {
1745  owl_list *l;
1746  owl_filter *f;
1747  int i, j;
1748  owl_fmtext fm;
1749
1750  owl_fmtext_init_null(&fm);
1751
1752  l=owl_global_get_filterlist(&g);
1753  j=owl_list_get_size(l);
1754
1755  owl_fmtext_append_bold(&fm, "Filters:\n");
1756
1757  for (i=0; i<j; i++) {
1758    f=owl_list_get_element(l, i);
1759    owl_fmtext_append_normal(&fm, "   ");
1760    if (owl_global_get_hascolors(&g)) {
1761      owl_fmtext_append_normal_color(&fm, owl_filter_get_name(f), owl_filter_get_color(f));
1762    } else {
1763      owl_fmtext_append_normal(&fm, owl_filter_get_name(f));
1764    }
1765    owl_fmtext_append_normal(&fm, "\n");
1766  }
1767  owl_function_popless_fmtext(&fm);
1768  owl_fmtext_free(&fm);
1769}
1770
1771void owl_function_show_filter(char *name) {
1772  owl_filter *f;
1773  char buff[5000];
1774
1775  f=owl_global_get_filter(&g, name);
1776  if (!f) {
1777    owl_function_makemsg("There is no filter with that name");
1778    return;
1779  }
1780  owl_filter_print(f, buff);
1781  owl_function_popless_text(buff);
1782}
1783
1784void owl_function_show_zpunts() {
1785  owl_filter *f;
1786  owl_list *fl;
1787  char buff[5000];
1788  owl_fmtext fm;
1789  int i, j;
1790
1791  owl_fmtext_init_null(&fm);
1792
1793  fl=owl_global_get_puntlist(&g);
1794  j=owl_list_get_size(fl);
1795  owl_fmtext_append_bold(&fm, "Active zpunt filters:\n");
1796
1797  for (i=0; i<j; i++) {
1798    f=owl_list_get_element(fl, i);
1799    owl_filter_print(f, buff);
1800    owl_fmtext_append_normal(&fm, buff);
1801  }
1802  owl_function_popless_fmtext(&fm);
1803  owl_fmtext_free(&fm);
1804}
1805
1806char *owl_function_fastclassinstfilt(char *class, char *instance) {
1807  /* creates a filter for a class, instance if one doesn't exist.
1808   * If instance is null then apply for all messgaes in the class.
1809   * returns the name of the filter, which the caller must free.*/
1810  owl_list *fl;
1811  owl_filter *f;
1812  char *argbuff, *filtname;
1813  int len;
1814
1815  fl=owl_global_get_filterlist(&g);
1816
1817  /* name for the filter */
1818  len=strlen(class)+30;
1819  if (instance) len+=strlen(instance);
1820  filtname=owl_malloc(len);
1821  if (!instance) {
1822    sprintf(filtname, "class-%s", class);
1823  } else {
1824    sprintf(filtname, "class-%s-instance-%s", class, instance);
1825  }
1826  downstr(filtname);
1827
1828  /* if it already exists then go with it.  This lets users override */
1829  if (owl_global_get_filter(&g, filtname)) {
1830    return filtname;
1831  }
1832
1833  /* create the new filter */
1834  argbuff=owl_malloc(len+20);
1835  sprintf(argbuff, "( class ^%s$ )", class);
1836  if (instance) {
1837    sprintf(argbuff, "%s and ( instance ^%s$ )", argbuff, instance);
1838  }
1839
1840  f=owl_malloc(sizeof(owl_filter));
1841  owl_filter_init_fromstring(f, filtname, argbuff);
1842
1843  /* add it to the global list */
1844  owl_global_add_filter(&g, f);
1845
1846  owl_free(argbuff);
1847  return filtname;
1848}
1849
1850char *owl_function_fastuserfilt(char *user) {
1851  owl_filter *f;
1852  char *argbuff, *longuser, *shortuser, *filtname;
1853
1854  /* stick the local realm on if it's not there */
1855  longuser=long_sender(user);
1856  shortuser=pretty_sender(user);
1857
1858  /* name for the filter */
1859  filtname=owl_malloc(strlen(shortuser)+20);
1860  sprintf(filtname, "user-%s", shortuser);
1861
1862  /* if it already exists then go with it.  This lets users override */
1863  if (owl_global_get_filter(&g, filtname)) {
1864    return filtname;
1865  }
1866
1867  /* create the new-internal filter */
1868  f=owl_malloc(sizeof(owl_filter));
1869
1870  argbuff=owl_malloc(strlen(longuser)+200);
1871  sprintf(argbuff, "( ( class ^message$ ) and ( instance ^personal$ ) and ( sender ^%s$ ) )", longuser);
1872  sprintf(argbuff, "%s or ( ( type ^admin$ ) and ( recipient %s ) )", argbuff, shortuser);
1873  sprintf(argbuff, "%s or ( ( class ^login$ ) and ( sender ^%s$ ) )", argbuff, longuser);
1874
1875  owl_filter_init_fromstring(f, filtname, argbuff);
1876
1877  /* add it to the global list */
1878  owl_global_add_filter(&g, f);
1879
1880  /* free stuff */
1881  owl_free(argbuff);
1882  owl_free(longuser);
1883  owl_free(shortuser);
1884
1885  return filtname;
1886}
1887
1888char *owl_function_fasttypefilt(char *type) {
1889  owl_filter *f;
1890  char *argbuff, *filtname;
1891
1892  /* name for the filter */
1893  filtname=owl_sprintf("type-%s", type);
1894
1895  /* if it already exists then go with it.  This lets users override */
1896  if (owl_global_get_filter(&g, filtname)) {
1897    return filtname;
1898  }
1899
1900  /* create the new-internal filter */
1901  f=owl_malloc(sizeof(owl_filter));
1902
1903  argbuff = owl_sprintf("type ^%s$", type);
1904
1905  owl_filter_init_fromstring(f, filtname, argbuff);
1906
1907  /* add it to the global list */
1908  owl_global_add_filter(&g, f);
1909
1910  /* free stuff */
1911  owl_free(argbuff);
1912
1913  return filtname;
1914}
1915
1916/* If flag is 1, marks for deletion.  If flag is 0,
1917 * unmarks for deletion. */
1918void owl_function_delete_curview_msgs(int flag) {
1919  owl_view *v;
1920  int i, j;
1921
1922  v=owl_global_get_current_view(&g);
1923  j=owl_view_get_size(v);
1924  for (i=0; i<j; i++) {
1925    if (flag == 1) {
1926      owl_message_mark_delete(owl_view_get_element(v, i));
1927    } else if (flag == 0) {
1928      owl_message_unmark_delete(owl_view_get_element(v, i));
1929    }
1930  }
1931
1932  owl_function_makemsg("%i messages marked for %sdeletion", j, flag?"":"un");
1933
1934  owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 
1935}
1936
1937char *owl_function_smartfilter(int type) {
1938  /* Returns the name of a filter, or null.  The caller
1939   * must free this name.  */
1940  /* if the curmsg is a personal message return a filter name
1941   *    to the converstaion with that user.
1942   * If the curmsg is a class message, instance foo, recip *
1943   *    message, return a filter name to the class, inst.
1944   * If the curmsg is a class message and type==0 then
1945   *    return a filter name for just the class.
1946   * If the curmsg is a class message and type==1 then
1947   *    return a filter name for the class and instance.
1948   */
1949  owl_view *v;
1950  owl_message *m;
1951  char *sender, *filtname=NULL;
1952 
1953  v=owl_global_get_current_view(&g);
1954  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
1955
1956  if (owl_view_get_size(v)==0) {
1957    owl_function_makemsg("No message selected\n");
1958    return NULL;
1959  }
1960
1961  /* very simple handling of admin messages for now */
1962  if (owl_message_is_admin(m)) {
1963    return owl_function_fasttypefilt("admin");
1964  }
1965
1966  /* narrow personal and login messages to the sender */
1967  if (owl_message_is_personal(m) || owl_message_is_login(m)) {
1968    if (owl_message_is_zephyr(m)) {
1969      sender=pretty_sender(owl_message_get_sender(m));
1970      filtname = owl_function_fastuserfilt(sender);
1971      owl_free(sender);
1972      return filtname;
1973    }
1974    return NULL;
1975  }
1976
1977  /* narrow class MESSAGE, instance foo, recip * messages to class, inst */
1978  if (!strcasecmp(owl_message_get_class(m), "message") &&
1979      !owl_message_is_personal(m)) {
1980    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
1981    return filtname;
1982  }
1983
1984  /* otherwise narrow to the class */
1985  if (type==0) {
1986    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), NULL);
1987  } else if (type==1) {
1988    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
1989  }
1990  return filtname;
1991}
1992
1993void owl_function_smartzpunt(int type) {
1994  /* Starts a zpunt command based on the current class,instance pair.
1995   * If type=0, uses just class.  If type=1, uses instance as well. */
1996  owl_view *v;
1997  owl_message *m;
1998  char *cmd, *cmdprefix, *mclass, *minst;
1999 
2000  v=owl_global_get_current_view(&g);
2001  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
2002
2003  if (owl_view_get_size(v)==0) {
2004    owl_function_makemsg("No message selected\n");
2005    return;
2006  }
2007
2008  /* for now we skip admin messages. */
2009  if (owl_message_is_admin(m)
2010      || owl_message_is_login(m)
2011      || !owl_message_is_zephyr(m)) {
2012    owl_function_makemsg("smartzpunt doesn't support this message type.");
2013    return;
2014  }
2015
2016  mclass = owl_message_get_class(m);
2017  minst = owl_message_get_instance(m);
2018  if (!mclass || !*mclass || *mclass==' '
2019      || (!strcasecmp(mclass, "message") && !strcasecmp(minst, "personal"))
2020      || (type && (!minst || !*minst|| *minst==' '))) {
2021    owl_function_makemsg("smartzpunt can't safely do this for <%s,%s>",
2022                         mclass, minst);
2023  } else {
2024    cmdprefix = "start-command zpunt ";
2025    cmd = owl_malloc(strlen(cmdprefix)+strlen(mclass)+strlen(minst)+3);
2026    strcpy(cmd, cmdprefix);
2027    strcat(cmd, mclass);
2028    if (type) {
2029      strcat(cmd, " ");
2030      strcat(cmd, minst);
2031    } else {
2032      strcat(cmd, " *");
2033    }
2034    owl_function_command(cmd);
2035    owl_free(cmd);
2036  }
2037}
2038
2039
2040
2041void owl_function_color_current_filter(char *color) {
2042  owl_filter *f;
2043  char *name;
2044
2045  name=owl_view_get_filtname(owl_global_get_current_view(&g));
2046  f=owl_global_get_filter(&g, name);
2047  if (!f) {
2048    owl_function_makemsg("Unknown filter");
2049    return;
2050  }
2051
2052  /* don't touch the all filter */
2053  if (!strcmp(name, "all")) {
2054    owl_function_makemsg("You may not change the 'all' filter.");
2055    return;
2056  }
2057
2058  /* deal with the case of trying change the filter color */
2059  owl_filter_set_color(f, owl_util_string_to_color(color));
2060  owl_global_set_needrefresh(&g);
2061  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2062}
2063
2064void owl_function_show_colors() {
2065  owl_fmtext fm;
2066
2067  owl_fmtext_init_null(&fm);
2068  owl_fmtext_append_normal_color(&fm, "default\n", OWL_COLOR_DEFAULT);
2069  owl_fmtext_append_normal_color(&fm, "red\n", OWL_COLOR_RED);
2070  owl_fmtext_append_normal_color(&fm, "green\n", OWL_COLOR_GREEN);
2071  owl_fmtext_append_normal_color(&fm, "yellow\n", OWL_COLOR_YELLOW);
2072  owl_fmtext_append_normal_color(&fm, "blue\n", OWL_COLOR_BLUE);
2073  owl_fmtext_append_normal_color(&fm, "magenta\n", OWL_COLOR_MAGENTA);
2074  owl_fmtext_append_normal_color(&fm, "cyan\n", OWL_COLOR_CYAN);
2075  owl_fmtext_append_normal_color(&fm, "white\n", OWL_COLOR_WHITE);
2076
2077  owl_function_popless_fmtext(&fm);
2078  owl_fmtext_free(&fm);
2079}
2080
2081void owl_function_zpunt(char *class, char *inst, char *recip, int direction) {
2082  /* add the given class, inst, recip to the punt list for filtering.
2083   *   if direction==0 then punt
2084   *   if direction==1 then unpunt */
2085  owl_filter *f;
2086  owl_list *fl;
2087  char *buff;
2088  int ret, i, j;
2089
2090  fl=owl_global_get_puntlist(&g);
2091
2092  /* first, create the filter */
2093  f=malloc(sizeof(owl_filter));
2094  buff=malloc(strlen(class)+strlen(inst)+strlen(recip)+100);
2095  if (!strcmp(recip, "*")) {
2096    sprintf(buff, "class ^%s$ and instance ^%s$", class, inst);
2097  } else {
2098    sprintf(buff, "class ^%s$ and instance ^%s$ and recipient %s", class, inst, recip);
2099  }
2100  owl_function_debugmsg("About to filter %s", buff);
2101  ret=owl_filter_init_fromstring(f, "punt-filter", buff);
2102  owl_free(buff);
2103  if (ret) {
2104    owl_function_makemsg("Error creating filter for zpunt");
2105    owl_filter_free(f);
2106    return;
2107  }
2108
2109  /* Check for an identical filter */
2110  j=owl_list_get_size(fl);
2111  for (i=0; i<j; i++) {
2112    if (owl_filter_equiv(f, owl_list_get_element(fl, i))) {
2113      /* if we're punting, then just silently bow out on this duplicate */
2114      if (direction==0) {
2115        owl_filter_free(f);
2116        return;
2117      }
2118
2119      /* if we're unpunting, then remove this filter from the puntlist */
2120      if (direction==1) {
2121        owl_filter_free(owl_list_get_element(fl, i));
2122        owl_list_remove_element(fl, i);
2123        return;
2124      }
2125    }
2126  }
2127
2128  /* If we're punting, add the filter to the global punt list */
2129  if (direction==0) {
2130    owl_list_append_element(fl, f);
2131  }
2132}
2133
2134void owl_function_activate_keymap(char *keymap) {
2135  if (!owl_keyhandler_activate(owl_global_get_keyhandler(&g), keymap)) {
2136    owl_function_makemsg("Unable to activate keymap '%s'", keymap);
2137  }
2138}
2139
2140
2141void owl_function_show_keymaps() {
2142  owl_list l;
2143  owl_fmtext fm;
2144  owl_keymap *km;
2145  owl_keyhandler *kh;
2146  int i, numkm;
2147  char *kmname;
2148
2149  kh = owl_global_get_keyhandler(&g);
2150  owl_fmtext_init_null(&fm);
2151  owl_fmtext_append_bold(&fm, "Keymaps:   ");
2152  owl_fmtext_append_normal(&fm, "(use 'show keymap <name>' for details)\n");
2153  owl_keyhandler_get_keymap_names(kh, &l);
2154  owl_fmtext_append_list(&fm, &l, "\n", owl_function_keymap_summary);
2155  owl_fmtext_append_normal(&fm, "\n");
2156
2157  numkm = owl_list_get_size(&l);
2158  for (i=0; i<numkm; i++) {
2159    kmname = owl_list_get_element(&l, i);
2160    km = owl_keyhandler_get_keymap(kh, kmname);
2161    owl_fmtext_append_bold(&fm, "\n\n----------------------------------------------------------------------------------------------------\n\n");
2162    owl_keymap_get_details(km, &fm);   
2163  }
2164  owl_fmtext_append_normal(&fm, "\n");
2165 
2166  owl_function_popless_fmtext(&fm);
2167  owl_keyhandler_keymap_namelist_free(&l);
2168  owl_fmtext_free(&fm);
2169}
2170
2171char *owl_function_keymap_summary(void *name) {
2172  owl_keymap *km
2173    = owl_keyhandler_get_keymap(owl_global_get_keyhandler(&g), name);
2174  if (km) return owl_keymap_summary(km);
2175  else return(NULL);
2176}
2177
2178/* TODO: implement for real */
2179void owl_function_show_keymap(char *name) {
2180  owl_fmtext  fm;
2181  owl_keymap *km;
2182
2183  owl_fmtext_init_null(&fm);
2184  km = owl_keyhandler_get_keymap(owl_global_get_keyhandler(&g), name);
2185  if (km) {
2186    owl_keymap_get_details(km, &fm);
2187  } else {
2188    owl_fmtext_append_normal(&fm, "No such keymap...\n");
2189  } 
2190  owl_function_popless_fmtext(&fm);
2191  owl_fmtext_free(&fm);
2192}
2193
2194
2195void owl_function_help_for_command(char *cmdname) {
2196  owl_fmtext   fm;
2197
2198  owl_fmtext_init_null(&fm);
2199  owl_cmd_get_help(owl_global_get_cmddict(&g), cmdname, &fm);
2200  owl_function_popless_fmtext(&fm); 
2201  owl_fmtext_free(&fm);
2202}
Note: See TracBrowser for help on using the repository browser.