source: functions.c @ 1aee7d9

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