source: functions.c @ fd93b41

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since fd93b41 was aa5f725, checked in by James M. Kretchmar <kretch@mit.edu>, 19 years ago
added buddylists added the 'alist' command to print logged in aimusers added the 'blist' command which prints buddies logged in from all protocols. 'l' is now bound to 'blist' by default
  • Property mode set to 100644
File size: 75.0 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 <sys/types.h>
9#include <sys/stat.h>
10#include <sys/wait.h>
11#include <errno.h>
12#include <signal.h>
13#include "owl.h"
14
15static const char fileIdent[] = "$Id$";
16
17void owl_function_noop(void)
18{
19  return;
20}
21
22char *owl_function_command(char *cmdbuff)
23{
24  owl_function_debugmsg("executing command: %s", cmdbuff);
25  return owl_cmddict_execute(owl_global_get_cmddict(&g), 
26                             owl_global_get_context(&g), cmdbuff);
27}
28
29void owl_function_command_norv(char *cmdbuff)
30{
31  char *rv;
32  rv=owl_function_command(cmdbuff);
33  if (rv) owl_free(rv);
34}
35
36void owl_function_command_alias(char *alias_from, char *alias_to)
37{
38  owl_cmddict_add_alias(owl_global_get_cmddict(&g), alias_from, alias_to);
39}
40
41owl_cmd *owl_function_get_cmd(char *name)
42{
43  return owl_cmddict_find(owl_global_get_cmddict(&g), name);
44}
45
46void owl_function_show_commands()
47{
48  owl_list l;
49  owl_fmtext fm;
50
51  owl_fmtext_init_null(&fm);
52  owl_fmtext_append_bold(&fm, "Commands:  ");
53  owl_fmtext_append_normal(&fm, "(use 'show command <name>' for details)\n");
54  owl_cmddict_get_names(owl_global_get_cmddict(&g), &l);
55  owl_fmtext_append_list(&fm, &l, "\n", owl_function_cmd_describe);
56  owl_fmtext_append_normal(&fm, "\n");
57  owl_function_popless_fmtext(&fm);
58  owl_cmddict_namelist_free(&l);
59  owl_fmtext_free(&fm);
60}
61
62char *owl_function_cmd_describe(void *name)
63{
64  owl_cmd *cmd = owl_cmddict_find(owl_global_get_cmddict(&g), name);
65  if (cmd) return owl_cmd_describe(cmd);
66  else return(NULL);
67}
68
69void owl_function_show_command(char *name)
70{
71  owl_function_help_for_command(name);
72}
73
74void owl_function_adminmsg(char *header, char *body)
75{
76  owl_message *m;
77  int followlast;
78
79  followlast=owl_global_should_followlast(&g);
80  m=owl_malloc(sizeof(owl_message));
81  owl_message_create_admin(m, header, body);
82  owl_messagelist_append_element(owl_global_get_msglist(&g), m);
83  owl_view_consider_message(owl_global_get_current_view(&g), m);
84
85  if (followlast) owl_function_lastmsg_noredisplay();
86
87  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
88  if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
89    owl_popwin_refresh(owl_global_get_popwin(&g));
90  }
91 
92  wnoutrefresh(owl_global_get_curs_recwin(&g));
93  owl_global_set_needrefresh(&g);
94}
95
96void owl_function_make_outgoing_zephyr(char *body, char *zwriteline, char *zsig)
97{
98  owl_message *m;
99  int followlast;
100  owl_zwrite z;
101 
102  followlast=owl_global_should_followlast(&g);
103
104  /* create a zwrite for the purpose of filling in other message fields */
105  owl_zwrite_create_from_line(&z, zwriteline);
106
107  /* create the message */
108  m=owl_malloc(sizeof(owl_message));
109  owl_message_create_from_zwriteline(m, zwriteline, body, zsig);
110
111  /* add it to the global list and current view */
112  owl_messagelist_append_element(owl_global_get_msglist(&g), m);
113  owl_view_consider_message(owl_global_get_current_view(&g), m);
114
115  if (followlast) owl_function_lastmsg_noredisplay();
116
117  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
118  if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
119    owl_popwin_refresh(owl_global_get_popwin(&g));
120  }
121 
122  wnoutrefresh(owl_global_get_curs_recwin(&g));
123  owl_global_set_needrefresh(&g);
124  owl_zwrite_free(&z);
125}
126
127int owl_function_make_outgoing_aim(char *body, char *to)
128{
129  owl_message *m;
130  int followlast;
131
132
133  if (!owl_global_is_aimloggedin(&g)) {
134    return(-1);
135  }
136 
137  followlast=owl_global_should_followlast(&g);
138
139  /* create the message */
140  m=owl_malloc(sizeof(owl_message));
141  owl_message_create_outgoing_aim(m, owl_global_get_aim_screenname(&g), to, body);
142
143  /* add it to the global list and current view */
144  owl_messagelist_append_element(owl_global_get_msglist(&g), m);
145  owl_view_consider_message(owl_global_get_current_view(&g), m);
146
147  if (followlast) owl_function_lastmsg_noredisplay();
148
149  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
150  if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
151    owl_popwin_refresh(owl_global_get_popwin(&g));
152  }
153 
154  wnoutrefresh(owl_global_get_curs_recwin(&g));
155  owl_global_set_needrefresh(&g);
156  return(0);
157}
158
159void owl_function_zwrite_setup(char *line)
160{
161  owl_editwin *e;
162  char buff[1024];
163  owl_zwrite z;
164  int ret;
165
166  /* check the arguments */
167  ret=owl_zwrite_create_from_line(&z, line);
168  if (ret) {
169    owl_function_makemsg("Error in zwrite arugments");
170    owl_zwrite_free(&z);
171    return;
172  }
173
174  /* send a ping if necessary */
175  if (owl_global_is_txping(&g)) {
176    owl_zwrite_send_ping(&z);
177  }
178  owl_zwrite_free(&z);
179
180  /* create and setup the editwin */
181  e=owl_global_get_typwin(&g);
182  owl_editwin_new_style(e, OWL_EDITWIN_STYLE_MULTILINE, owl_global_get_msg_history(&g));
183
184  if (!owl_global_get_lockout_ctrld(&g)) {
185    owl_function_makemsg("Type your zephyr below.  End with ^D or a dot on a line by itself.  ^C will quit.");
186  } else {
187    owl_function_makemsg("Type your zephyr below.  End with a dot on a line by itself.  ^C will quit.");
188  }
189
190  owl_editwin_clear(e);
191  owl_editwin_set_dotsend(e);
192  strcpy(buff, "----> ");
193  strcat(buff, line);
194  strcat(buff, "\n");
195  owl_editwin_set_locktext(e, buff);
196
197  /* make it active */
198  owl_global_set_typwin_active(&g);
199}
200
201void owl_function_aimwrite_setup(char *line)
202{
203  owl_editwin *e;
204  char buff[1024];
205
206  /* check the arguments */
207
208  /* create and setup the editwin */
209  e=owl_global_get_typwin(&g);
210  owl_editwin_new_style(e, OWL_EDITWIN_STYLE_MULTILINE, owl_global_get_msg_history(&g));
211
212  if (!owl_global_get_lockout_ctrld(&g)) {
213    owl_function_makemsg("Type your message below.  End with ^D or a dot on a line by itself.  ^C will quit.");
214  } else {
215    owl_function_makemsg("Type your message below.  End with a dot on a line by itself.  ^C will quit.");
216  }
217
218  owl_editwin_clear(e);
219  owl_editwin_set_dotsend(e);
220  strcpy(buff, "----> ");
221  strcat(buff, line);
222  strcat(buff, "\n");
223  owl_editwin_set_locktext(e, buff);
224
225  /* make it active */
226  owl_global_set_typwin_active(&g);
227}
228
229
230
231void owl_function_zcrypt_setup(char *line)
232{
233  owl_editwin *e;
234  char buff[1024];
235  owl_zwrite z;
236  int ret;
237
238  /* check the arguments */
239  ret=owl_zwrite_create_from_line(&z, line);
240  if (ret) {
241    owl_function_makemsg("Error in zwrite arugments");
242    owl_zwrite_free(&z);
243    return;
244  }
245
246  if (owl_zwrite_get_numrecips(&z)>0) {
247    owl_function_makemsg("You may not specifiy a recipient for a zcrypt message");
248    owl_zwrite_free(&z);
249    return;
250  }
251
252  /* send a ping if necessary */
253  if (owl_global_is_txping(&g)) {
254    owl_zwrite_send_ping(&z);
255  }
256  owl_zwrite_free(&z);
257
258  /* create and setup the editwin */
259  e=owl_global_get_typwin(&g);
260  owl_editwin_new_style(e, OWL_EDITWIN_STYLE_MULTILINE, owl_global_get_msg_history(&g));
261
262  if (!owl_global_get_lockout_ctrld(&g)) {
263    owl_function_makemsg("Type your zephyr below.  End with ^D or a dot on a line by itself.  ^C will quit.");
264  } else {
265    owl_function_makemsg("Type your zephyr below.  End with a dot on a line by itself.  ^C will quit.");
266  }
267
268  owl_editwin_clear(e);
269  owl_editwin_set_dotsend(e);
270  strcpy(buff, "----> ");
271  strcat(buff, line);
272  strcat(buff, "\n");
273  owl_editwin_set_locktext(e, buff);
274
275  /* make it active */
276  owl_global_set_typwin_active(&g);
277}
278
279void owl_function_zwrite(char *line)
280{
281  owl_zwrite z;
282  int i, j;
283
284  /* create the zwrite and send the message */
285  owl_zwrite_create_from_line(&z, line);
286  owl_zwrite_send_message(&z, owl_editwin_get_text(owl_global_get_typwin(&g)));
287  owl_function_makemsg("Waiting for ack...");
288
289  /* display the message as an outgoing message in the receive window */
290  if (owl_global_is_displayoutgoing(&g) && owl_zwrite_is_personal(&z)) {
291    owl_function_make_outgoing_zephyr(owl_editwin_get_text(owl_global_get_typwin(&g)), line, owl_zwrite_get_zsig(&z));
292  }
293
294  /* log it if we have logging turned on */
295  if (owl_global_is_logging(&g) && owl_zwrite_is_personal(&z)) {
296    j=owl_zwrite_get_numrecips(&z);
297    for (i=0; i<j; i++) {
298      owl_log_outgoing(owl_zwrite_get_recip_n(&z, i),
299                       owl_editwin_get_text(owl_global_get_typwin(&g)));
300    }
301  }
302
303  /* free the zwrite */
304  owl_zwrite_free(&z);
305}
306
307
308void owl_function_aimwrite(char *to)
309{
310  /*  send the message */
311  owl_aim_send_im(to, owl_editwin_get_text(owl_global_get_typwin(&g)));
312  owl_function_makemsg("AIM message sent.");
313
314  /* display the message as an outgoing message in the receive window */
315  if (owl_global_is_displayoutgoing(&g)) {
316    owl_function_make_outgoing_aim(owl_editwin_get_text(owl_global_get_typwin(&g)), to);
317  }
318
319  /* not yet */
320#if 0
321  /* log it if we have logging turned on */
322  if (owl_global_is_logging(&g)) {
323    owl_log_outgoing(to, owl_editwin_get_text(owl_global_get_typwin(&g)));
324  }
325#endif
326}
327
328
329
330/* If filter is non-null, looks for the next message matching
331 * that filter.  If skip_deleted, skips any deleted messages.
332 * If last_if_none, will stop at the last message in the view
333 * if no matching messages are found.  */
334void owl_function_nextmsg_full(char *filter, int skip_deleted, int last_if_none)
335{
336  int curmsg, i, viewsize, found;
337  owl_view *v;
338  owl_filter *f = NULL;
339  owl_message *m;
340
341  v=owl_global_get_current_view(&g);
342
343  if (filter) {
344    f=owl_global_get_filter(&g, filter);
345    if (!f) {
346      owl_function_makemsg("No %s filter defined", filter);
347      return;
348    }
349  }
350
351  curmsg=owl_global_get_curmsg(&g);
352  viewsize=owl_view_get_size(v);
353  found=0;
354
355  /* just check to make sure we're in bounds... */
356  if (curmsg>viewsize-1) curmsg=viewsize-1;
357  if (curmsg<0) curmsg=0;
358
359  for (i=curmsg+1; i<viewsize; i++) {
360    m=owl_view_get_element(v, i);
361    if (skip_deleted && owl_message_is_delete(m)) continue;
362    if (f && !owl_filter_message_match(f, m)) continue;
363    found = 1;
364    break;
365  }
366
367  if (i>owl_view_get_size(v)-1) i=owl_view_get_size(v)-1;
368
369  if (!found) {
370    owl_function_makemsg("already at last%s message%s%s",
371                         skip_deleted?" non-deleted":"",
372                         filter?" in ":"", filter?filter:"");
373    /* if (!skip_deleted) owl_function_beep(); */
374  }
375
376  if (last_if_none || found) {
377    owl_global_set_curmsg(&g, i);
378    owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
379    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
380    owl_global_set_direction_downwards(&g);
381  }
382}
383
384void owl_function_prevmsg_full(char *filter, int skip_deleted, int first_if_none)
385{
386  int curmsg, i, viewsize, found;
387  owl_view *v;
388  owl_filter *f = NULL;
389  owl_message *m;
390
391  v=owl_global_get_current_view(&g);
392
393  if (filter) {
394    f=owl_global_get_filter(&g, filter);
395    if (!f) {
396      owl_function_makemsg("No %s filter defined", filter);
397      return;
398    }
399  }
400
401  curmsg=owl_global_get_curmsg(&g);
402  viewsize=owl_view_get_size(v);
403  found=0;
404
405  /* just check to make sure we're in bounds... */
406  if (curmsg<0) curmsg=0;
407
408  for (i=curmsg-1; i>=0; i--) {
409    m=owl_view_get_element(v, i);
410    if (skip_deleted && owl_message_is_delete(m)) continue;
411    if (f && !owl_filter_message_match(f, m)) continue;
412    found = 1;
413    break;
414  }
415
416  if (i<0) i=0;
417
418  if (!found) {
419    owl_function_makemsg("already at first%s message%s%s",
420                         skip_deleted?" non-deleted":"",
421                         filter?" in ":"", filter?filter:"");
422    /* if (!skip_deleted) owl_function_beep(); */
423  }
424
425  if (first_if_none || found) {
426    owl_global_set_curmsg(&g, i);
427    owl_function_calculate_topmsg(OWL_DIRECTION_UPWARDS);
428    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
429    owl_global_set_direction_upwards(&g);
430  }
431}
432
433void owl_function_nextmsg()
434{
435  owl_function_nextmsg_full(NULL, 0, 1);
436}
437
438
439void owl_function_prevmsg()
440{
441  owl_function_prevmsg_full(NULL, 0, 1);
442}
443
444void owl_function_nextmsg_notdeleted()
445{
446  owl_function_nextmsg_full(NULL, 1, 1);
447}
448
449void owl_function_prevmsg_notdeleted()
450{
451  owl_function_prevmsg_full(NULL, 1, 1);
452}
453
454
455void owl_function_nextmsg_personal()
456{
457  owl_function_nextmsg_full("personal", 0, 0);
458}
459
460void owl_function_prevmsg_personal()
461{
462  owl_function_prevmsg_full("personal", 0, 0);
463}
464
465
466/* if move_after is 1, moves after the delete */
467void owl_function_deletecur(int move_after)
468{
469  int curmsg;
470  owl_view *v;
471
472  v=owl_global_get_current_view(&g);
473
474  /* bail if there's no current message */
475  if (owl_view_get_size(v) < 1) {
476    owl_function_makemsg("No current message to delete");
477    return;
478  }
479
480  /* mark the message for deletion */
481  curmsg=owl_global_get_curmsg(&g);
482  owl_view_delete_element(v, curmsg);
483
484  if (move_after) {
485    /* move the poiner in the appropriate direction
486     * to the next undeleted msg */
487    if (owl_global_get_direction(&g)==OWL_DIRECTION_UPWARDS) {
488      owl_function_prevmsg_notdeleted();
489    } else {
490      owl_function_nextmsg_notdeleted();
491    }
492  }
493}
494
495
496void owl_function_undeletecur(int move_after)
497{
498  int curmsg;
499  owl_view *v;
500
501  v=owl_global_get_current_view(&g);
502 
503  if (owl_view_get_size(v) < 1) {
504    owl_function_makemsg("No current message to undelete");
505    return;
506  }
507  curmsg=owl_global_get_curmsg(&g);
508
509  owl_view_undelete_element(v, curmsg);
510
511  if (move_after) {
512    if (owl_global_get_direction(&g)==OWL_DIRECTION_UPWARDS) {
513      if (curmsg>0) {
514        owl_function_prevmsg();
515      } else {
516        owl_function_nextmsg();
517      }
518    } else {
519      owl_function_nextmsg();
520    }
521  }
522
523  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
524}
525
526
527void owl_function_expunge()
528{
529  int curmsg;
530  owl_message *m;
531  owl_messagelist *ml;
532  owl_view *v;
533  int lastmsgid=0;
534
535  curmsg=owl_global_get_curmsg(&g);
536  v=owl_global_get_current_view(&g);
537  ml=owl_global_get_msglist(&g);
538
539  m=owl_view_get_element(v, curmsg);
540  if (m) lastmsgid = owl_message_get_id(m);
541
542  /* expunge the message list */
543  owl_messagelist_expunge(ml);
544
545  /* update all views (we only have one right now) */
546  owl_view_recalculate(v);
547
548  /* find where the new position should be
549     (as close as possible to where we last where) */
550  curmsg = owl_view_get_nearest_to_msgid(v, lastmsgid);
551  if (curmsg>owl_view_get_size(v)-1) curmsg = owl_view_get_size(v)-1;
552  if (curmsg<0) curmsg = 0;
553  owl_global_set_curmsg(&g, curmsg);
554  owl_function_calculate_topmsg(OWL_DIRECTION_NONE);
555  /* if there are no messages set the direction to down in case we
556     delete everything upwards */
557  owl_global_set_direction_downwards(&g);
558 
559  owl_function_makemsg("Messages expunged");
560  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
561}
562
563
564void owl_function_firstmsg()
565{
566  owl_global_set_curmsg(&g, 0);
567  owl_global_set_topmsg(&g, 0);
568  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
569  owl_global_set_direction_downwards(&g);
570}
571
572void owl_function_lastmsg_noredisplay()
573{
574  int oldcurmsg, curmsg;
575  owl_view *v;
576
577  v=owl_global_get_current_view(&g);
578  oldcurmsg=owl_global_get_curmsg(&g);
579  curmsg=owl_view_get_size(v)-1; 
580  if (curmsg<0) curmsg=0;
581  owl_global_set_curmsg(&g, curmsg);
582  if (oldcurmsg < curmsg) {
583    owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
584  } else if (curmsg<owl_view_get_size(v)) {
585    /* If already at the end, blank the screen and move curmsg
586     * past the end of the messages. */
587    owl_global_set_topmsg(&g, curmsg+1);
588    owl_global_set_curmsg(&g, curmsg+1);
589  } 
590  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
591  owl_global_set_direction_downwards(&g);
592}
593
594void owl_function_lastmsg()
595{
596  owl_function_lastmsg_noredisplay();
597  owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 
598}
599
600void owl_function_shift_right()
601{
602  owl_global_set_rightshift(&g, owl_global_get_rightshift(&g)+10);
603  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
604  owl_global_set_needrefresh(&g);
605}
606
607
608void owl_function_shift_left()
609{
610  int shift;
611
612  shift=owl_global_get_rightshift(&g);
613  if (shift>=10) {
614    owl_global_set_rightshift(&g, shift-10);
615    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
616    owl_global_set_needrefresh(&g);
617  } else {
618    owl_function_beep();
619    owl_function_makemsg("Already full left");
620  }
621}
622
623
624void owl_function_unsuball()
625{
626  unsuball();
627  owl_function_makemsg("Unsubscribed from all messages.");
628}
629
630void owl_function_loadsubs(char *file)
631{
632  int ret;
633
634  ret=owl_zephyr_loadsubs(file);
635
636  if (!owl_context_is_interactive(owl_global_get_context(&g))) return;
637  if (ret==0) {
638    owl_function_makemsg("Subscribed to messages from file.");
639  } else if (ret==-1) {
640    owl_function_makemsg("Could not open file.");
641  } else {
642    owl_function_makemsg("Error subscribing to messages from file.");
643  }
644}
645
646void owl_function_loadloginsubs(char *file)
647{
648  int ret;
649
650  ret=owl_zephyr_loadloginsubs(file);
651
652  if (!owl_context_is_interactive(owl_global_get_context(&g))) return;
653  if (ret==0) {
654    owl_function_makemsg("Subscribed to login messages from file.");
655  } else if (ret==-1) {
656    owl_function_makemsg("Could not open file for login subscriptions.");
657  } else {
658    owl_function_makemsg("Error subscribing to login messages from file.");
659  }
660}
661
662void owl_function_suspend()
663{
664  endwin();
665  printf("\n");
666  kill(getpid(), SIGSTOP);
667
668  /* resize to reinitialize all the windows when we come back */
669  owl_command_resize();
670}
671
672void owl_function_zaway_toggle()
673{
674  if (!owl_global_is_zaway(&g)) {
675    owl_global_set_zaway_msg(&g, owl_global_get_zaway_msg_default(&g));
676    owl_function_zaway_on();
677  } else {
678    owl_function_zaway_off();
679  }
680}
681
682void owl_function_zaway_on()
683{
684  owl_global_set_zaway_on(&g);
685  owl_function_makemsg("zaway set (%s)", owl_global_get_zaway_msg(&g));
686}
687
688void owl_function_zaway_off()
689{
690  owl_global_set_zaway_off(&g);
691  owl_function_makemsg("zaway off");
692}
693
694void owl_function_quit()
695{
696  char *ret;
697 
698  /* zlog out if we need to */
699  if (owl_global_is_shutdownlogout(&g)) {
700    owl_zephyr_zlog_out();
701  }
702
703  /* execute the commands in shutdown */
704  ret = owl_config_execute("owl::shutdown();");
705  if (ret) owl_free(ret);
706
707  /* signal our child process, if any */
708  if (owl_global_get_newmsgproc_pid(&g)) {
709    kill(owl_global_get_newmsgproc_pid(&g), SIGHUP);
710  }
711
712  /* final clean up */
713  unsuball();
714  ZClosePort();
715  endwin();
716  owl_function_debugmsg("Quitting Owl");
717  exit(0);
718}
719
720
721void owl_function_makemsg(char *fmt, ...)
722{
723  va_list ap;
724  char buff[2048];
725
726  va_start(ap, fmt);
727  werase(owl_global_get_curs_msgwin(&g));
728 
729  vsnprintf(buff, 2048, fmt, ap);
730  owl_function_debugmsg("makemsg: %s", buff);
731  waddstr(owl_global_get_curs_msgwin(&g), buff); 
732  wnoutrefresh(owl_global_get_curs_msgwin(&g));
733  owl_global_set_needrefresh(&g);
734  va_end(ap);
735}
736
737void owl_function_errormsg(char *fmt, ...)
738{
739  va_list ap;
740  char buff[2048];
741
742  va_start(ap, fmt);
743  werase(owl_global_get_curs_msgwin(&g));
744 
745  vsnprintf(buff, 2048, fmt, ap);
746  owl_function_debugmsg("ERROR: %s", buff);
747  waddstr(owl_global_get_curs_msgwin(&g), buff); 
748  waddstr(owl_global_get_curs_msgwin(&g), "ERROR: "); 
749  wnoutrefresh(owl_global_get_curs_msgwin(&g));
750  owl_global_set_needrefresh(&g);
751  va_end(ap);
752}
753
754
755void owl_function_openurl()
756{
757  /* visit the first url in the current message */
758  owl_message *m;
759  owl_view *v;
760  char *ptr1, *ptr2, *text, url[LINE], tmpbuff[LINE];
761  int webbrowser;
762
763  webbrowser = owl_global_get_webbrowser(&g);
764
765  if (webbrowser < 0 || webbrowser == OWL_WEBBROWSER_NONE) {
766    owl_function_makemsg("No browser selected");
767    return;
768  }
769
770  v=owl_global_get_current_view(&g);
771 
772  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
773
774  if (!m || owl_view_get_size(v)==0) {
775    owl_function_makemsg("No current message selected");
776    return;
777  }
778
779  text=owl_message_get_text(m);
780
781  /* First look for a good URL */ 
782  if ((ptr1=strstr(text, "http://"))!=NULL) {
783    ptr2=strpbrk(ptr1, " \n\t");
784    if (ptr2) {
785      strncpy(url, ptr1, ptr2-ptr1+1);
786      url[ptr2-ptr1+1]='\0';
787    } else {
788      strcpy(url, ptr1);
789    }
790
791    /* if we had <http strip a trailing > */
792    if (ptr1>text && ptr1[-1]=='<') {
793      if (url[strlen(url)-1]=='>') {
794        url[strlen(url)-1]='\0';
795      }
796    }
797  } else if ((ptr1=strstr(text, "https://"))!=NULL) {
798    /* Look for an https URL */ 
799    ptr2=strpbrk(ptr1, " \n\t");
800    if (ptr2) {
801      strncpy(url, ptr1, ptr2-ptr1+1);
802      url[ptr2-ptr1+1]='\0';
803    } else {
804      strcpy(url, ptr1);
805    }
806   
807    /* if we had <http strip a trailing > */
808    if (ptr1>text && ptr1[-1]=='<') {
809      if (url[strlen(url)-1]=='>') {
810        url[strlen(url)-1]='\0';
811      }
812    }
813  } else if ((ptr1=strstr(text, "www."))!=NULL) {
814    /* if we can't find a real url look for www.something */
815    ptr2=strpbrk(ptr1, " \n\t");
816    if (ptr2) {
817      strncpy(url, ptr1, ptr2-ptr1+1);
818      url[ptr2-ptr1+1]='\0';
819    } else {
820      strcpy(url, ptr1);
821    }
822  } else {
823    owl_function_beep();
824    owl_function_makemsg("Could not find URL to open.");
825    return;
826  }
827
828  /* Make sure there aren't any quotes or \'s in the url */
829  for (ptr1 = url; *ptr1; ptr1++) {
830    if (*ptr1 == '"' || *ptr1 == '\\') {
831      owl_function_beep();
832      owl_function_makemsg("URL contains invalid characters.");
833      return;
834    }
835  }
836 
837  /* NOTE: There are potentially serious security issues here... */
838
839  /* open the page */
840  owl_function_makemsg("Opening %s", url);
841  if (webbrowser == OWL_WEBBROWSER_NETSCAPE) {
842    snprintf(tmpbuff, LINE, "netscape -remote \"openURL(%s)\" > /dev/null 2> /dev/null", url);
843    system(tmpbuff); 
844  } else if (webbrowser == OWL_WEBBROWSER_GALEON) {
845    snprintf(tmpbuff, LINE, "galeon \"%s\" > /dev/null 2> /dev/null &", url);
846    system(tmpbuff); 
847  } else if (webbrowser == OWL_WEBBROWSER_OPERA) {
848    snprintf(tmpbuff, LINE, "opera \"%s\" > /dev/null 2> /dev/null &", url);
849    system(tmpbuff); 
850  }
851}
852
853void owl_function_calculate_topmsg(int direction)
854{
855  int recwinlines, topmsg, curmsg;
856  owl_view *v;
857
858  v=owl_global_get_current_view(&g);
859  curmsg=owl_global_get_curmsg(&g);
860  topmsg=owl_global_get_topmsg(&g);
861  recwinlines=owl_global_get_recwin_lines(&g);
862
863  /*
864  if (owl_view_get_size(v) < 1) {
865    return;
866  }
867  */
868
869  switch (owl_global_get_scrollmode(&g)) {
870  case OWL_SCROLLMODE_TOP:
871    topmsg = owl_function_calculate_topmsg_top(direction, v, curmsg, topmsg, recwinlines);
872    break;
873  case OWL_SCROLLMODE_NEARTOP:
874    topmsg = owl_function_calculate_topmsg_neartop(direction, v, curmsg, topmsg, recwinlines);
875    break;
876  case OWL_SCROLLMODE_CENTER:
877    topmsg = owl_function_calculate_topmsg_center(direction, v, curmsg, topmsg, recwinlines);
878    break;
879  case OWL_SCROLLMODE_PAGED:
880    topmsg = owl_function_calculate_topmsg_paged(direction, v, curmsg, topmsg, recwinlines, 0);
881    break;
882  case OWL_SCROLLMODE_PAGEDCENTER:
883    topmsg = owl_function_calculate_topmsg_paged(direction, v, curmsg, topmsg, recwinlines, 1);
884    break;
885  case OWL_SCROLLMODE_NORMAL:
886  default:
887    topmsg = owl_function_calculate_topmsg_normal(direction, v, curmsg, topmsg, recwinlines);
888  }
889  owl_function_debugmsg("Calculated a topmsg of %i", topmsg);
890  owl_global_set_topmsg(&g, topmsg);
891}
892
893/* Returns what the new topmsg should be. 
894 * Passed the last direction of movement,
895 * the current view,
896 * the current message number in the view,
897 * the top message currently being displayed,
898 * and the number of lines in the recwin.
899 */
900int owl_function_calculate_topmsg_top(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines)
901{
902  return(curmsg);
903}
904
905int owl_function_calculate_topmsg_neartop(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines)
906{
907  if (curmsg>0 
908      && (owl_message_get_numlines(owl_view_get_element(v, curmsg-1))
909          <  recwinlines/2)) {
910    return(curmsg-1);
911  } else {
912    return(curmsg);
913  }
914}
915 
916int owl_function_calculate_topmsg_center(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines)
917{
918  int i, last, lines;
919
920  last = curmsg;
921  lines = 0;
922  for (i=curmsg-1; i>=0; i--) {
923    lines += owl_message_get_numlines(owl_view_get_element(v, i));
924    if (lines > recwinlines/2) break;
925    last = i;
926  }
927  return(last);
928}
929 
930int owl_function_calculate_topmsg_paged(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines, int center_on_page)
931{
932  int i, last, lines, savey;
933 
934  /* If we're off the top of the screen, scroll up such that the
935   * curmsg is near the botton of the screen. */
936  if (curmsg < topmsg) {
937    last = curmsg;
938    lines = 0;
939    for (i=curmsg; i>=0; i--) {
940      lines += owl_message_get_numlines(owl_view_get_element(v, i));
941      if (lines > recwinlines) break;
942    last = i;
943    }
944    if (center_on_page) {
945      return(owl_function_calculate_topmsg_center(direction, v, curmsg, 0, recwinlines));
946    } else {
947      return(last);
948    }
949  }
950
951  /* Find number of lines from top to bottom of curmsg (store in savey) */
952  savey=0;
953  for (i=topmsg; i<=curmsg; i++) {
954    savey+=owl_message_get_numlines(owl_view_get_element(v, i));
955  }
956
957  /* if we're off the bottom of the screen, scroll down */
958  if (savey > recwinlines) {
959    if (center_on_page) {
960      return(owl_function_calculate_topmsg_center(direction, v, curmsg, 0, recwinlines));
961    } else {
962      return(curmsg);
963    }
964  }
965
966  /* else just stay as we are... */
967  return(topmsg);
968}
969
970
971int owl_function_calculate_topmsg_normal(int direction, owl_view *v, int curmsg, int topmsg, int recwinlines)
972{
973  int savey, j, i, foo, y;
974
975  if (curmsg<0) return(topmsg);
976   
977  /* If we're off the top of the screen then center */
978  if (curmsg<topmsg) {
979    topmsg=owl_function_calculate_topmsg_center(direction, v, curmsg, 0, recwinlines);
980  }
981
982  /* Find number of lines from top to bottom of curmsg (store in savey) */
983  savey=0;
984  for (i=topmsg; i<=curmsg; i++) {
985    savey+=owl_message_get_numlines(owl_view_get_element(v, i));
986  }
987
988  /* If we're off the bottom of the screen, set the topmsg to curmsg
989   * and scroll upwards */
990  if (savey > recwinlines) {
991    topmsg=curmsg;
992    savey=owl_message_get_numlines(owl_view_get_element(v, i));
993    direction=OWL_DIRECTION_UPWARDS;
994  }
995 
996  /* If our bottom line is less than 1/4 down the screen then scroll up */
997  if (direction == OWL_DIRECTION_UPWARDS || direction == OWL_DIRECTION_NONE) {
998    if (savey < (recwinlines / 4)) {
999      y=0;
1000      for (j=curmsg; j>=0; j--) {
1001        foo=owl_message_get_numlines(owl_view_get_element(v, j));
1002        /* will we run the curmsg off the screen? */
1003        if ((foo+y) >= recwinlines) {
1004          j++;
1005          if (j>curmsg) j=curmsg;
1006          break;
1007        }
1008        /* have saved 1/2 the screen space? */
1009        y+=foo;
1010        if (y > (recwinlines / 2)) break;
1011      }
1012      if (j<0) j=0;
1013      return(j);
1014    }
1015  }
1016
1017  if (direction == OWL_DIRECTION_DOWNWARDS || direction == OWL_DIRECTION_NONE) {
1018    /* If curmsg bottom line is more than 3/4 down the screen then scroll down */
1019    if (savey > ((recwinlines * 3)/4)) {
1020      y=0;
1021      /* count lines from the top until we can save 1/2 the screen size */
1022      for (j=topmsg; j<curmsg; j++) {
1023        y+=owl_message_get_numlines(owl_view_get_element(v, j));
1024        if (y > (recwinlines / 2)) break;
1025      }
1026      if (j==curmsg) {
1027        j--;
1028      }
1029      return(j+1);
1030    }
1031  }
1032
1033  return(topmsg);
1034}
1035
1036
1037void owl_function_resize()
1038{
1039  owl_global_set_resize_pending(&g);
1040}
1041
1042
1043void owl_function_run_buffercommand()
1044{
1045  char *buff;
1046
1047  buff=owl_global_get_buffercommand(&g);
1048  if (!strncmp(buff, "zwrite ", 7)) {
1049    owl_function_zwrite(buff);
1050  } else if (!strncmp(buff, "aimwrite ", 9)) {
1051    owl_function_aimwrite(buff+9);
1052  }
1053}
1054
1055void owl_function_debugmsg(char *fmt, ...)
1056{
1057  FILE *file;
1058  time_t now;
1059  char buff1[LINE], buff2[LINE];
1060  va_list ap;
1061  va_start(ap, fmt);
1062
1063  if (!owl_global_is_debug_fast(&g)) return;
1064
1065  file=fopen(owl_global_get_debug_file(&g), "a");
1066  if (!file) return;
1067
1068  now=time(NULL);
1069  strcpy(buff1, ctime(&now));
1070  buff1[strlen(buff1)-1]='\0';
1071
1072  owl_global_get_runtime_string(&g, buff2);
1073 
1074  fprintf(file, "[%i -  %s - %s]: ", (int) getpid(), buff1, buff2);
1075  vfprintf(file, fmt, ap);
1076  fprintf(file, "\n");
1077  fclose(file);
1078
1079  va_end(ap);
1080}
1081
1082
1083void owl_function_refresh()
1084{
1085  owl_function_resize();
1086}
1087
1088void owl_function_beep()
1089{
1090  if (owl_global_is_bell(&g)) {
1091    beep();
1092    owl_global_set_needrefresh(&g); /* do we really need this? */
1093  }
1094}
1095
1096
1097void owl_function_subscribe(char *class, char *inst, char *recip)
1098{
1099  int ret;
1100
1101  ret=owl_zephyr_sub(class, inst, recip);
1102  if (ret) {
1103    owl_function_makemsg("Error subscribing.");
1104  } else {
1105    owl_function_makemsg("Subscribed.");
1106  }
1107}
1108
1109
1110void owl_function_unsubscribe(char *class, char *inst, char *recip)
1111{
1112  int ret;
1113
1114  ret=owl_zephyr_unsub(class, inst, recip);
1115  if (ret) {
1116    owl_function_makemsg("Error subscribing.");
1117  } else {
1118    owl_function_makemsg("Unsubscribed.");
1119  }
1120}
1121
1122
1123void owl_function_set_cursor(WINDOW *win)
1124{
1125  wnoutrefresh(win);
1126}
1127
1128
1129void owl_function_full_redisplay()
1130{
1131  redrawwin(owl_global_get_curs_recwin(&g));
1132  redrawwin(owl_global_get_curs_sepwin(&g));
1133  redrawwin(owl_global_get_curs_typwin(&g));
1134  redrawwin(owl_global_get_curs_msgwin(&g));
1135
1136  wnoutrefresh(owl_global_get_curs_recwin(&g));
1137  wnoutrefresh(owl_global_get_curs_sepwin(&g));
1138  wnoutrefresh(owl_global_get_curs_typwin(&g));
1139  wnoutrefresh(owl_global_get_curs_msgwin(&g));
1140 
1141  sepbar("");
1142  owl_function_makemsg("");
1143
1144  owl_global_set_needrefresh(&g);
1145}
1146
1147
1148void owl_function_popless_text(char *text)
1149{
1150  owl_popwin *pw;
1151  owl_viewwin *v;
1152
1153  pw=owl_global_get_popwin(&g);
1154  v=owl_global_get_viewwin(&g);
1155
1156  owl_popwin_up(pw);
1157  owl_viewwin_init_text(v, owl_popwin_get_curswin(pw),
1158                        owl_popwin_get_lines(pw), owl_popwin_get_cols(pw),
1159                        text);
1160  owl_popwin_refresh(pw);
1161  owl_viewwin_redisplay(v, 0);
1162  owl_global_set_needrefresh(&g);
1163}
1164
1165
1166void owl_function_popless_fmtext(owl_fmtext *fm)
1167{
1168  owl_popwin *pw;
1169  owl_viewwin *v;
1170
1171  pw=owl_global_get_popwin(&g);
1172  v=owl_global_get_viewwin(&g);
1173
1174  owl_popwin_up(pw);
1175  owl_viewwin_init_fmtext(v, owl_popwin_get_curswin(pw),
1176                   owl_popwin_get_lines(pw), owl_popwin_get_cols(pw),
1177                   fm);
1178  owl_popwin_refresh(pw);
1179  owl_viewwin_redisplay(v, 0);
1180  owl_global_set_needrefresh(&g);
1181}
1182
1183void owl_function_about()
1184{
1185  char buff[5000];
1186
1187  sprintf(buff, "This is owl version %s\n", OWL_VERSION_STRING);
1188  strcat(buff, "\nOwl was written by James Kretchmar at the Massachusetts\n");
1189  strcat(buff, "Institute of Technology.  The first version, 0.5, was\n");
1190  strcat(buff, "released in March 2002.\n");
1191  strcat(buff, "\n");
1192  strcat(buff, "The name 'owl' was chosen in reference to the owls in the\n");
1193  strcat(buff, "Harry Potter novels, who are tasked with carrying messages\n");
1194  strcat(buff, "between Witches and Wizards.\n");
1195  strcat(buff, "\n");
1196  strcat(buff, "Copyright 2002 Massachusetts Institute of Technology\n");
1197  strcat(buff, "\n");
1198  strcat(buff, "Permission to use, copy, modify, and distribute this\n");
1199  strcat(buff, "software and its documentation for any purpose and without\n");
1200  strcat(buff, "fee is hereby granted, provided that the above copyright\n");
1201  strcat(buff, "notice and this permission notice appear in all copies\n");
1202  strcat(buff, "and in supporting documentation.  No representation is\n");
1203  strcat(buff, "made about the suitability of this software for any\n");
1204  strcat(buff, "purpose.  It is provided \"as is\" without express\n");
1205  strcat(buff, "or implied warranty.\n");
1206  owl_function_popless_text(buff);
1207}
1208
1209void owl_function_info()
1210{
1211  owl_message *m;
1212  owl_fmtext fm;
1213  ZNotice_t *n;
1214  char buff[10000], tmpbuff[1024];
1215  char *ptr;
1216  int i, j, fields, len;
1217  owl_view *v;
1218
1219  owl_fmtext_init_null(&fm);
1220 
1221  v=owl_global_get_current_view(&g);
1222  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
1223  if (!m || owl_view_get_size(v)==0) {
1224    owl_function_makemsg("No message selected\n");
1225    return;
1226  }
1227
1228  owl_fmtext_append_normal(&fm, "Msg Id    : ");
1229  sprintf(buff, "%i", owl_message_get_id(m));
1230  owl_fmtext_append_normal(&fm, buff);
1231  owl_fmtext_append_normal(&fm, "\n");
1232
1233  owl_fmtext_append_normal(&fm, "Type      : ");
1234  owl_fmtext_append_bold(&fm, owl_message_type_to_string(m));
1235  owl_fmtext_append_normal(&fm, "\n");
1236
1237  if (owl_message_is_direction_in(m)) {
1238    owl_fmtext_append_normal(&fm, "Direction : in\n");
1239  } else if (owl_message_is_direction_out(m)) {
1240    owl_fmtext_append_normal(&fm, "Direction : out\n");
1241  } else if (owl_message_is_direction_none(m)) {
1242    owl_fmtext_append_normal(&fm, "Direction : none\n");
1243  } else {
1244    owl_fmtext_append_normal(&fm, "Direction : unknown\n");
1245  }
1246
1247  owl_fmtext_append_normal(&fm, "Time      : ");
1248  owl_fmtext_append_normal(&fm, owl_message_get_timestr(m));
1249  owl_fmtext_append_normal(&fm, "\n");
1250
1251  if (!owl_message_is_type_admin(m)) {
1252    owl_fmtext_append_normal(&fm, "Sender    : ");
1253    owl_fmtext_append_normal(&fm, owl_message_get_sender(m));
1254    owl_fmtext_append_normal(&fm, "\n");
1255   
1256    owl_fmtext_append_normal(&fm, "Recipient : ");
1257    owl_fmtext_append_normal(&fm, owl_message_get_recipient(m));
1258    owl_fmtext_append_normal(&fm, "\n");
1259  }
1260   
1261  if (owl_message_is_type_zephyr(m)) {
1262    owl_fmtext_append_bold(&fm, "  Zephyr Specific Info\n");
1263   
1264    owl_fmtext_append_normal(&fm, "Class     : ");
1265    owl_fmtext_append_normal(&fm, owl_message_get_class(m));
1266    owl_fmtext_append_normal(&fm, "\n");
1267    owl_fmtext_append_normal(&fm, "Instance  : ");
1268    owl_fmtext_append_normal(&fm, owl_message_get_instance(m));
1269    owl_fmtext_append_normal(&fm, "\n");
1270    owl_fmtext_append_normal(&fm, "Opcode    : ");
1271    owl_fmtext_append_normal(&fm, owl_message_get_opcode(m));
1272    owl_fmtext_append_normal(&fm, "\n");
1273   
1274    owl_fmtext_append_normal(&fm, "Time      : ");
1275    owl_fmtext_append_normal(&fm, owl_message_get_timestr(m));
1276    owl_fmtext_append_normal(&fm, "\n");
1277
1278    if (owl_message_is_direction_in(m)) {
1279      n=owl_message_get_notice(m);
1280
1281      owl_fmtext_append_normal(&fm, "Kind      : ");
1282      if (n->z_kind==UNSAFE) {
1283        owl_fmtext_append_normal(&fm, "UNSAFE\n");
1284      } else if (n->z_kind==UNACKED) {
1285        owl_fmtext_append_normal(&fm, "UNACKED\n");
1286      } else if (n->z_kind==ACKED) {
1287        owl_fmtext_append_normal(&fm, "ACKED\n");
1288      } else if (n->z_kind==HMACK) {
1289        owl_fmtext_append_normal(&fm, "HMACK\n");
1290      } else if (n->z_kind==HMCTL) {
1291        owl_fmtext_append_normal(&fm, "HMCTL\n");
1292      } else if (n->z_kind==SERVACK) {
1293        owl_fmtext_append_normal(&fm, "SERVACK\n");
1294      } else if (n->z_kind==SERVNAK) {
1295        owl_fmtext_append_normal(&fm, "SERVNACK\n");
1296      } else if (n->z_kind==CLIENTACK) {
1297        owl_fmtext_append_normal(&fm, "CLIENTACK\n");
1298      } else if (n->z_kind==STAT) {
1299        owl_fmtext_append_normal(&fm, "STAT\n");
1300      } else {
1301        owl_fmtext_append_normal(&fm, "ILLEGAL VALUE\n");
1302      }
1303      owl_fmtext_append_normal(&fm, "Host      : ");
1304      owl_fmtext_append_normal(&fm, owl_message_get_hostname(m));
1305      owl_fmtext_append_normal(&fm, "\n");
1306      sprintf(buff, "Port      : %i\n", n->z_port);
1307      owl_fmtext_append_normal(&fm, buff);
1308
1309      owl_fmtext_append_normal(&fm,    "Auth      : ");
1310      if (n->z_auth == ZAUTH_FAILED) {
1311        owl_fmtext_append_normal(&fm, "FAILED\n");
1312      } else if (n->z_auth == ZAUTH_NO) {
1313        owl_fmtext_append_normal(&fm, "NO\n");
1314      } else if (n->z_auth == ZAUTH_YES) {
1315        owl_fmtext_append_normal(&fm, "YES\n");
1316      } else {
1317        sprintf(buff, "Unknown State (%i)\n", n->z_auth);
1318        owl_fmtext_append_normal(&fm, buff);
1319      }
1320
1321      sprintf(buff, "Checkd Ath: %i\n", n->z_checked_auth);
1322      sprintf(buff, "%sMulti notc: %s\n", buff, n->z_multinotice);
1323      sprintf(buff, "%sNum other : %i\n", buff, n->z_num_other_fields);
1324      sprintf(buff, "%sMsg Len   : %i\n", buff, n->z_message_len);
1325      owl_fmtext_append_normal(&fm, buff);
1326     
1327      sprintf(buff, "Fields    : %i\n", owl_zephyr_get_num_fields(n));
1328      owl_fmtext_append_normal(&fm, buff);
1329     
1330      fields=owl_zephyr_get_num_fields(n);
1331      for (i=0; i<fields; i++) {
1332        sprintf(buff, "Field %i   : ", i+1);
1333       
1334        ptr=owl_zephyr_get_field(n, i+1, &len);
1335        if (!ptr) break;
1336        if (len<30) {
1337          strncpy(tmpbuff, ptr, len);
1338          tmpbuff[len]='\0';
1339        } else {
1340          strncpy(tmpbuff, ptr, 30);
1341          tmpbuff[30]='\0';
1342          strcat(tmpbuff, "...");
1343        }
1344       
1345        for (j=0; j<strlen(tmpbuff); j++) {
1346          if (tmpbuff[j]=='\n') tmpbuff[j]='~';
1347          if (tmpbuff[j]=='\r') tmpbuff[j]='!';
1348        }
1349       
1350        strcat(buff, tmpbuff);
1351        strcat(buff, "\n");
1352        owl_fmtext_append_normal(&fm, buff);
1353      }
1354      owl_fmtext_append_normal(&fm, "Default Fm:");
1355      owl_fmtext_append_normal(&fm, n->z_default_format);
1356    }
1357  }
1358
1359  if (owl_message_is_type_aim(m)) {
1360    owl_fmtext_append_bold(&fm, "  AIM Specific Info\n");   
1361  }
1362 
1363  owl_function_popless_fmtext(&fm);
1364}
1365
1366
1367void owl_function_curmsg_to_popwin()
1368{
1369  owl_popwin *pw;
1370  owl_view *v;
1371  owl_message *m;
1372
1373  v = owl_global_get_current_view(&g);
1374
1375  pw=owl_global_get_popwin(&g);
1376
1377  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
1378
1379  if (!m || owl_view_get_size(v)==0) {
1380    owl_function_makemsg("No current message");
1381    return;
1382  }
1383
1384  owl_function_popless_fmtext(owl_message_get_fmtext(m));
1385}
1386
1387
1388void owl_function_page_curmsg(int step)
1389{
1390  /* scroll down or up within the current message IF the message is truncated */
1391
1392  int offset, curmsg, lines;
1393  owl_view *v;
1394  owl_message *m;
1395
1396  offset=owl_global_get_curmsg_vert_offset(&g);
1397  v=owl_global_get_current_view(&g);
1398  curmsg=owl_global_get_curmsg(&g);
1399  m=owl_view_get_element(v, curmsg);
1400  if (!m || owl_view_get_size(v)==0) return;
1401  lines=owl_message_get_numlines(m);
1402
1403  if (offset==0) {
1404    /* Bail if the curmsg isn't the last one displayed */
1405    if (curmsg != owl_mainwin_get_last_msg(owl_global_get_mainwin(&g))) {
1406      owl_function_makemsg("The entire message is already displayed");
1407      return;
1408    }
1409   
1410    /* Bail if we're not truncated */
1411    if (!owl_mainwin_is_curmsg_truncated(owl_global_get_mainwin(&g))) {
1412      owl_function_makemsg("The entire message is already displayed");
1413      return;
1414    }
1415  }
1416 
1417 
1418  /* don't scroll past the last line */
1419  if (step>0) {
1420    if (offset+step > lines-1) {
1421      owl_global_set_curmsg_vert_offset(&g, lines-1);
1422    } else {
1423      owl_global_set_curmsg_vert_offset(&g, offset+step);
1424    }
1425  }
1426
1427  /* would we be before the beginning of the message? */
1428  if (step<0) {
1429    if (offset+step<0) {
1430      owl_global_set_curmsg_vert_offset(&g, 0);
1431    } else {
1432      owl_global_set_curmsg_vert_offset(&g, offset+step);
1433    }
1434  }
1435 
1436  /* redisplay */
1437  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1438  owl_global_set_needrefresh(&g);
1439}
1440
1441void owl_function_resize_typwin(int newsize)
1442{
1443  owl_global_set_typwin_lines(&g, newsize);
1444  owl_function_resize();
1445}
1446
1447void owl_function_typwin_grow()
1448{
1449  int i;
1450
1451  i=owl_global_get_typwin_lines(&g);
1452  owl_function_resize_typwin(i+1);
1453}
1454
1455void owl_function_typwin_shrink()
1456{
1457  int i;
1458
1459  i=owl_global_get_typwin_lines(&g);
1460  if (i>2) {
1461    owl_function_resize_typwin(i-1);
1462  }
1463}
1464
1465void owl_function_mainwin_pagedown()
1466{
1467  int i;
1468
1469  i=owl_mainwin_get_last_msg(owl_global_get_mainwin(&g));
1470  if (i<0) return;
1471  if (owl_mainwin_is_last_msg_truncated(owl_global_get_mainwin(&g))
1472      && (owl_global_get_curmsg(&g) < i)
1473      && (i>0)) {
1474    i--;
1475  }
1476  owl_global_set_curmsg(&g, i);
1477  owl_function_nextmsg();
1478}
1479
1480void owl_function_mainwin_pageup()
1481{
1482  owl_global_set_curmsg(&g, owl_global_get_topmsg(&g));
1483  owl_function_prevmsg();
1484}
1485
1486void owl_function_getsubs()
1487{
1488  int ret, num, i, one;
1489  ZSubscription_t sub;
1490  char *buff, *tmpbuff;
1491
1492  one = 1;
1493
1494  ret=ZRetrieveSubscriptions(0, &num);
1495  if (ret == ZERR_TOOMANYSUBS) {
1496    owl_function_makemsg("Zephyr: too many subscriptions");
1497    return;
1498  }
1499
1500  buff=owl_malloc(num*500);
1501  tmpbuff=owl_malloc(num*500);
1502  strcpy(buff, "");
1503  for (i=0; i<num; i++) {
1504    if ((ret = ZGetSubscriptions(&sub, &one)) != ZERR_NONE) {
1505      owl_function_makemsg("Error while getting subscriptions");
1506      owl_free(buff);
1507      owl_free(tmpbuff);
1508      ZFlushSubscriptions();
1509      return;
1510    } else {
1511      sprintf(tmpbuff, "<%s,%s,%s>\n%s", sub.zsub_class, sub.zsub_classinst, sub.zsub_recipient, buff);
1512      strcpy(buff, tmpbuff);
1513    }
1514  }
1515
1516  owl_function_popless_text(buff);
1517  owl_free(buff);
1518  owl_free(tmpbuff);
1519  ZFlushSubscriptions();
1520}
1521
1522#define PABUFLEN 5000
1523void owl_function_printallvars()
1524{
1525  char buff[PABUFLEN], *pos, *name;
1526  owl_list varnames;
1527  int i, numvarnames, rem;
1528
1529  pos = buff;
1530  pos += sprintf(pos, "%-20s = %s\n", "VARIABLE", "VALUE");
1531  pos += sprintf(pos, "%-20s   %s\n",  "--------", "-----");
1532  owl_variable_dict_get_names(owl_global_get_vardict(&g), &varnames);
1533  rem = (buff+PABUFLEN)-pos-1;
1534  numvarnames = owl_list_get_size(&varnames);
1535  for (i=0; i<numvarnames; i++) {
1536    name = owl_list_get_element(&varnames, i);
1537    if (name && name[0]!='_') {
1538      rem = (buff+PABUFLEN)-pos-1;   
1539      pos += snprintf(pos, rem, "\n%-20s = ", name);
1540      rem = (buff+PABUFLEN)-pos-1;   
1541      owl_variable_get_tostring(owl_global_get_vardict(&g), name, pos, rem);
1542      pos = buff+strlen(buff);
1543    }
1544  }
1545  rem = (buff+PABUFLEN)-pos-1;   
1546  snprintf(pos, rem, "\n");
1547  owl_variable_dict_namelist_free(&varnames);
1548 
1549  owl_function_popless_text(buff);
1550}
1551
1552void owl_function_show_variables()
1553{
1554  owl_list varnames;
1555  owl_fmtext fm; 
1556  int i, numvarnames;
1557  char *varname;
1558
1559  owl_fmtext_init_null(&fm);
1560  owl_fmtext_append_bold(&fm, 
1561      "Variables: (use 'show variable <name>' for details)\n");
1562  owl_variable_dict_get_names(owl_global_get_vardict(&g), &varnames);
1563  numvarnames = owl_list_get_size(&varnames);
1564  for (i=0; i<numvarnames; i++) {
1565    varname = owl_list_get_element(&varnames, i);
1566    if (varname && varname[0]!='_') {
1567      owl_variable_describe(owl_global_get_vardict(&g), varname, &fm);
1568    }
1569  }
1570  owl_variable_dict_namelist_free(&varnames);
1571  owl_function_popless_fmtext(&fm);
1572  owl_fmtext_free(&fm);
1573}
1574
1575void owl_function_show_variable(char *name)
1576{
1577  owl_fmtext fm; 
1578
1579  owl_fmtext_init_null(&fm);
1580  owl_variable_get_help(owl_global_get_vardict(&g), name, &fm);
1581  owl_function_popless_fmtext(&fm);
1582  owl_fmtext_free(&fm); 
1583}
1584
1585/* note: this applies to global message list, not to view.
1586 * If flag is 1, deletes.  If flag is 0, undeletes. */
1587void owl_function_delete_by_id(int id, int flag)
1588{
1589  owl_messagelist *ml;
1590  owl_message *m;
1591  ml = owl_global_get_msglist(&g);
1592  m = owl_messagelist_get_by_id(ml, id);
1593  if (m) {
1594    if (flag == 1) {
1595      owl_message_mark_delete(m);
1596    } else if (flag == 0) {
1597      owl_message_unmark_delete(m);
1598    }
1599    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1600    owl_global_set_needrefresh(&g);
1601  } else {
1602    owl_function_makemsg("No message with id %d: unable to mark for (un)delete",id);
1603  }
1604}
1605
1606void owl_function_delete_automsgs()
1607{
1608  /* mark for deletion all messages in the current view that match the
1609   * 'trash' filter */
1610
1611  int i, j, count;
1612  owl_message *m;
1613  owl_view *v;
1614  owl_filter *f;
1615
1616  /* get the trash filter */
1617  f=owl_global_get_filter(&g, "trash");
1618  if (!f) {
1619    owl_function_makemsg("No trash filter defined");
1620    return;
1621  }
1622
1623  v=owl_global_get_current_view(&g);
1624
1625  count=0;
1626  j=owl_view_get_size(v);
1627  for (i=0; i<j; i++) {
1628    m=owl_view_get_element(v, i);
1629    if (owl_filter_message_match(f, m)) {
1630      count++;
1631      owl_message_mark_delete(m);
1632    }
1633  }
1634  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1635  owl_function_makemsg("%i messages marked for deletion", count);
1636  owl_global_set_needrefresh(&g);
1637}
1638
1639
1640void owl_function_status()
1641{
1642  char buff[5000];
1643  time_t start;
1644  int up, days, hours, minutes;
1645
1646  start=owl_global_get_starttime(&g);
1647
1648  sprintf(buff, "Version: %s\n", OWL_VERSION_STRING);
1649  sprintf(buff, "%sScreen size: %i lines, %i columns\n", buff, owl_global_get_lines(&g), owl_global_get_cols(&g));
1650  sprintf(buff, "%sStartup Arugments: %s\n", buff, owl_global_get_startupargs(&g));
1651  sprintf(buff, "%sStartup Time: %s", buff, ctime(&start));
1652
1653  up=owl_global_get_runtime(&g);
1654  days=up/86400;
1655  up-=days*86400;
1656  hours=up/3600;
1657  up-=hours*3600;
1658  minutes=up/60;
1659  up-=minutes*60;
1660  sprintf(buff, "%sRun Time: %i days %2.2i:%2.2i:%2.2i\n", buff, days, hours, minutes, up);
1661
1662  if (owl_global_get_hascolors(&g)) {
1663    sprintf(buff, "%sColor: Yes, %i color pairs.\n", buff, owl_global_get_colorpairs(&g));
1664  } else {
1665    strcat(buff, "Color: No.\n");
1666  }
1667
1668  sprintf(buff, "%sMemory Malloced: %i\n", buff, owl_global_get_malloced(&g));
1669  sprintf(buff, "%sMemory Freed: %i\n", buff, owl_global_get_freed(&g));
1670  sprintf(buff, "%sMemory In Use: %i\n", buff, owl_global_get_meminuse(&g));
1671
1672  owl_function_popless_text(buff);
1673}
1674
1675void owl_function_show_term()
1676{
1677  owl_fmtext fm;
1678  char buff[LINE];
1679
1680  owl_fmtext_init_null(&fm);
1681  sprintf(buff, "Terminal Lines: %i\nTerminal Columns: %i\n",
1682          owl_global_get_lines(&g),
1683          owl_global_get_cols(&g));
1684  owl_fmtext_append_normal(&fm, buff);
1685
1686  if (owl_global_get_hascolors(&g)) {
1687    owl_fmtext_append_normal(&fm, "Color: Yes\n");
1688    sprintf(buff, "Number of color pairs: %i\n", owl_global_get_colorpairs(&g));
1689    owl_fmtext_append_normal(&fm, buff);
1690    sprintf(buff, "Can change colors: %s\n", can_change_color() ? "yes" : "no");
1691    owl_fmtext_append_normal(&fm, buff);
1692  } else {
1693    owl_fmtext_append_normal(&fm, "Color: No\n");
1694  }
1695
1696  owl_function_popless_fmtext(&fm);
1697  owl_fmtext_free(&fm);
1698}
1699
1700
1701void owl_function_reply(int type, int enter)
1702{
1703  /* if type = 0 then normal reply.
1704   * if type = 1 then it's a reply to sender
1705   * if enter = 0 then allow the command to be edited
1706   * if enter = 1 then don't wait for editing
1707   */
1708  char *buff, *oldbuff;
1709  owl_message *m;
1710  owl_filter *f;
1711 
1712  if (owl_view_get_size(owl_global_get_current_view(&g))==0) {
1713    owl_function_makemsg("No message selected");
1714  } else {
1715    char *class, *inst, *to, *cc=NULL;
1716   
1717    m=owl_view_get_element(owl_global_get_current_view(&g), owl_global_get_curmsg(&g));
1718    if (!m) {
1719      owl_function_makemsg("No message selected");
1720      return;
1721    }
1722
1723    /* first check if we catch the reply-lockout filter */
1724    f=owl_global_get_filter(&g, "reply-lockout");
1725    if (f) {
1726      if (owl_filter_message_match(f, m)) {
1727        owl_function_makemsg("Sorry, replies to this message have been disabled by the reply-lockout filter");
1728        return;
1729      }
1730    }
1731
1732    /* admin */
1733    if (owl_message_is_type_admin(m)) {
1734      owl_function_makemsg("You cannot reply to an admin message");
1735      return;
1736    }
1737
1738    /* zephyr */
1739    if (owl_message_is_type_zephyr(m)) {
1740      /* for now we disable replies to zcrypt messages, since we can't
1741         support an encrypted reply */
1742      if (!strcasecmp(owl_message_get_opcode(m), "crypt")) {
1743        owl_function_makemsg("Replies to zcrypt messages are not enabled in this release");
1744        return;
1745      }
1746
1747      if (owl_message_is_direction_out(m)) {
1748        owl_function_zwrite_setup(owl_message_get_zwriteline(m));
1749        owl_global_set_buffercommand(&g, owl_message_get_zwriteline(m));
1750        return;
1751      }
1752     
1753      if (owl_message_is_login(m)) {
1754        class="MESSAGE";
1755        inst="PERSONAL";
1756        to=owl_message_get_sender(m);
1757      } else if (type==1) {
1758        class="MESSAGE";
1759        inst="PERSONAL";
1760        to=owl_message_get_sender(m);
1761      } else {
1762        class=owl_message_get_class(m);
1763        inst=owl_message_get_instance(m);
1764        to=owl_message_get_recipient(m);
1765        cc=owl_message_get_cc(m);
1766        if (!strcmp(to, "") || !strcmp(to, "*")) {
1767          to="";
1768        } else if (to[0]=='@') {
1769          /* leave it, to get the realm */
1770        } else {
1771          to=owl_message_get_sender(m);
1772        }
1773      }
1774       
1775      /* create the command line */
1776      buff = owl_strdup("zwrite");
1777      if (strcasecmp(class, "message")) {
1778        buff = owl_sprintf("%s -c %s%s%s", oldbuff=buff, owl_getquoting(class), class, owl_getquoting(class));
1779        owl_free(oldbuff);
1780      }
1781      if (strcasecmp(inst, "personal")) {
1782        buff = owl_sprintf("%s -i %s%s%s", oldbuff=buff, owl_getquoting(inst), inst, owl_getquoting(inst));
1783        owl_free(oldbuff);
1784      }
1785      if (*to != '\0') {
1786        char *tmp, *oldtmp, *tmp2;
1787        tmp=short_zuser(to);
1788        if (cc) {
1789          tmp = owl_util_uniq(oldtmp=tmp, cc, "-");
1790          owl_free(oldtmp);
1791          buff = owl_sprintf("%s -C %s", oldbuff=buff, tmp);
1792          owl_free(oldbuff);
1793        } else {
1794          if (owl_global_is_smartstrip(&g)) {
1795            tmp2=tmp;
1796            tmp=owl_util_smartstripped_user(tmp2);
1797            owl_free(tmp2);
1798          }
1799          buff = owl_sprintf("%s %s", oldbuff=buff, tmp);
1800          owl_free(oldbuff);
1801        }
1802        owl_free(tmp);
1803      }
1804      if (cc) owl_free(cc);
1805    }
1806
1807    /* aim */
1808    if (owl_message_is_type_aim(m)) {
1809      if (owl_message_is_direction_out(m)) {
1810        buff=owl_sprintf("aimwrite %s", owl_message_get_recipient(m));
1811      } else {
1812        buff=owl_sprintf("aimwrite %s", owl_message_get_sender(m));
1813      }
1814    }
1815   
1816    if (enter) {
1817      owl_history *hist = owl_global_get_cmd_history(&g);
1818      owl_history_store(hist, buff);
1819      owl_history_reset(hist);
1820      owl_function_command_norv(buff);
1821    } else {
1822      owl_function_start_command(buff);
1823    }
1824    owl_free(buff);
1825  }
1826}
1827
1828void owl_function_zlocate(int argc, char **argv, int auth)
1829{
1830  owl_fmtext fm;
1831  char *ptr, buff[LINE];
1832  int i;
1833
1834  owl_fmtext_init_null(&fm);
1835
1836  for (i=0; i<argc; i++) {
1837    ptr=long_zuser(argv[i]);
1838    owl_zephyr_zlocate(ptr, buff, auth);
1839    owl_fmtext_append_normal(&fm, buff);
1840    owl_free(ptr);
1841  }
1842
1843  owl_function_popless_fmtext(&fm);
1844  owl_fmtext_free(&fm);
1845}
1846
1847void owl_function_start_command(char *line)
1848{
1849  int i, j;
1850  owl_editwin *tw;
1851
1852  tw=owl_global_get_typwin(&g);
1853  owl_global_set_typwin_active(&g);
1854  owl_editwin_new_style(tw, OWL_EDITWIN_STYLE_ONELINE, 
1855                        owl_global_get_cmd_history(&g));
1856
1857  owl_editwin_set_locktext(tw, "command: ");
1858  owl_global_set_needrefresh(&g);
1859
1860  j=strlen(line);
1861  for (i=0; i<j; i++) {
1862    owl_editwin_process_char(tw, line[i]);
1863  }
1864  owl_editwin_redisplay(tw, 0);
1865}
1866
1867char *owl_function_exec(int argc, char **argv, char *buff, int type)
1868{
1869  /* if type == 1 display in a popup
1870   * if type == 2 display an admin messages
1871   * if type == 0 return output
1872   * else display in a popup
1873   */
1874  char *newbuff, *redirect = " 2>&1 < /dev/null";
1875  char *out, buff2[1024];
1876  int size;
1877  FILE *p;
1878
1879  if (argc<2) {
1880    owl_function_makemsg("Wrong number of arguments to the exec command");
1881    return NULL;
1882  }
1883
1884  buff = skiptokens(buff, 1);
1885  newbuff = owl_malloc(strlen(buff)+strlen(redirect)+1);
1886  strcpy(newbuff, buff);
1887  strcat(newbuff, redirect);
1888
1889  p=popen(newbuff, "r");
1890  out=owl_malloc(1024);
1891  size=1024;
1892  strcpy(out, "");
1893  while (fgets(buff2, 1024, p)!=NULL) {
1894    size+=1024;
1895    out=owl_realloc(out, size);
1896    strcat(out, buff2);
1897  }
1898  pclose(p);
1899
1900  if (type==1) {
1901    owl_function_popless_text(out);
1902  } else if (type==0) {
1903    return out;
1904  } else if (type==2) {
1905    owl_function_adminmsg(buff, out);
1906  } else {
1907    owl_function_popless_text(out);
1908  }
1909  owl_free(out);
1910  return NULL;
1911}
1912
1913
1914char *owl_function_perl(int argc, char **argv, char *buff, int type)
1915{
1916  /* if type == 1 display in a popup
1917   * if type == 2 display an admin messages
1918   * if type == 0 return output
1919   * else display in a popup
1920   */
1921  char *perlout;
1922
1923  if (argc<2) {
1924    owl_function_makemsg("Wrong number of arguments to perl command");
1925    return NULL;
1926  }
1927
1928  /* consume first token (argv[0]) */
1929  buff = skiptokens(buff, 1);
1930
1931  perlout = owl_config_execute(buff);
1932  if (perlout) { 
1933    if (type==1) {
1934      owl_function_popless_text(perlout);
1935    } else if (type==2) {
1936      owl_function_adminmsg(buff, perlout);
1937    } else if (type==0) {
1938      return perlout;
1939    } else {
1940      owl_function_popless_text(perlout);
1941    }
1942    owl_free(perlout);
1943  }
1944  return NULL;
1945}
1946
1947
1948void owl_function_change_view(char *filtname)
1949{
1950  owl_view *v;
1951  owl_filter *f;
1952  int curid=-1, newpos, curmsg;
1953  owl_message *curm=NULL;
1954
1955  v=owl_global_get_current_view(&g);
1956  curmsg=owl_global_get_curmsg(&g);
1957  if (curmsg==-1) {
1958    owl_function_debugmsg("Hit the curmsg==-1 case in change_view");
1959  } else {
1960    curm=owl_view_get_element(v, curmsg);
1961    if (curm) {
1962      curid=owl_message_get_id(curm);
1963      owl_view_save_curmsgid(v, curid);
1964    }
1965  }
1966
1967  /* grab the filter */;
1968  f=owl_global_get_filter(&g, filtname);
1969  if (!f) {
1970    owl_function_makemsg("Unknown filter");
1971    return;
1972  }
1973
1974  /* free the existing view and create a new one based on the filter */
1975  owl_view_free(v);
1976  owl_view_create(v, f);
1977
1978  /* Figure out what to set the current message to.
1979   * - If the view we're leaving has messages in it, go to the closest message
1980   *   to the last message pointed to in that view.
1981   * - If the view we're leaving is empty, try to restore the position
1982   *   from the last time we were in the new view.  */
1983  if (curm) {
1984    newpos = owl_view_get_nearest_to_msgid(v, curid);
1985  } else {
1986    newpos = owl_view_get_nearest_to_saved(v);
1987  }
1988
1989  owl_global_set_curmsg(&g, newpos);
1990
1991  owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
1992  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
1993  owl_global_set_direction_downwards(&g);
1994}
1995
1996void owl_function_create_filter(int argc, char **argv)
1997{
1998  owl_filter *f;
1999  owl_view *v;
2000  int ret, inuse=0;
2001
2002  if (argc < 2) {
2003    owl_function_makemsg("Wrong number of arguments to filter command");
2004    return;
2005  }
2006
2007  v=owl_global_get_current_view(&g);
2008
2009  /* don't touch the all filter */
2010  if (!strcmp(argv[1], "all")) {
2011    owl_function_makemsg("You may not change the 'all' filter.");
2012    return;
2013  }
2014
2015  /* deal with the case of trying change the filter color */
2016  if (argc==4 && !strcmp(argv[2], "-c")) {
2017    f=owl_global_get_filter(&g, argv[1]);
2018    if (!f) {
2019      owl_function_makemsg("The filter '%s' does not exist.", argv[1]);
2020      return;
2021    }
2022    owl_filter_set_color(f, owl_util_string_to_color(argv[3]));
2023    owl_global_set_needrefresh(&g);
2024    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2025    return;
2026  }
2027
2028  /* create the filter and check for errors */
2029  f=owl_malloc(sizeof(owl_filter));
2030  ret=owl_filter_init(f, argv[1], argc-2, argv+2);
2031  if (ret==-1) {
2032    owl_free(f);
2033    owl_function_makemsg("Invalid filter syntax");
2034    return;
2035  }
2036
2037  /* if the named filter is in use by the current view, remember it */
2038  if (!strcmp(owl_view_get_filtname(v), argv[1])) {
2039    inuse=1;
2040  }
2041
2042  /* if the named filter already exists, nuke it */
2043  if (owl_global_get_filter(&g, argv[1])) {
2044    owl_global_remove_filter(&g, argv[1]);
2045  }
2046
2047  /* add the filter */
2048  owl_global_add_filter(&g, f);
2049
2050  /* if it was in use by the current view then update */
2051  if (inuse) {
2052    owl_function_change_view(argv[1]);
2053  }
2054  owl_global_set_needrefresh(&g);
2055  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2056}
2057
2058void owl_function_show_filters()
2059{
2060  owl_list *l;
2061  owl_filter *f;
2062  int i, j;
2063  owl_fmtext fm;
2064
2065  owl_fmtext_init_null(&fm);
2066
2067  l=owl_global_get_filterlist(&g);
2068  j=owl_list_get_size(l);
2069
2070  owl_fmtext_append_bold(&fm, "Filters:\n");
2071
2072  for (i=0; i<j; i++) {
2073    f=owl_list_get_element(l, i);
2074    owl_fmtext_append_normal(&fm, "   ");
2075    if (owl_global_get_hascolors(&g)) {
2076      owl_fmtext_append_normal_color(&fm, owl_filter_get_name(f), owl_filter_get_color(f));
2077    } else {
2078      owl_fmtext_append_normal(&fm, owl_filter_get_name(f));
2079    }
2080    owl_fmtext_append_normal(&fm, "\n");
2081  }
2082  owl_function_popless_fmtext(&fm);
2083  owl_fmtext_free(&fm);
2084}
2085
2086void owl_function_show_filter(char *name)
2087{
2088  owl_filter *f;
2089  char buff[5000];
2090
2091  f=owl_global_get_filter(&g, name);
2092  if (!f) {
2093    owl_function_makemsg("There is no filter with that name");
2094    return;
2095  }
2096  owl_filter_print(f, buff);
2097  owl_function_popless_text(buff);
2098}
2099
2100void owl_function_show_zpunts()
2101{
2102  owl_filter *f;
2103  owl_list *fl;
2104  char buff[5000];
2105  owl_fmtext fm;
2106  int i, j;
2107
2108  owl_fmtext_init_null(&fm);
2109
2110  fl=owl_global_get_puntlist(&g);
2111  j=owl_list_get_size(fl);
2112  owl_fmtext_append_bold(&fm, "Active zpunt filters:\n");
2113
2114  for (i=0; i<j; i++) {
2115    f=owl_list_get_element(fl, i);
2116    owl_filter_print(f, buff);
2117    owl_fmtext_append_normal(&fm, buff);
2118  }
2119  owl_function_popless_fmtext(&fm);
2120  owl_fmtext_free(&fm);
2121}
2122
2123/* Create a filter for a class, instance if one doesn't exist.  If
2124 * instance is NULL then catch all messgaes in the class.  Returns the
2125 * name of the filter, which the caller must free.
2126 */
2127char *owl_function_classinstfilt(char *class, char *instance) 
2128{
2129  owl_list *fl;
2130  owl_filter *f;
2131  char *argbuff, *filtname;
2132  char *tmpclass, *tmpinstance = NULL;
2133  int len;
2134
2135  fl=owl_global_get_filterlist(&g);
2136
2137  /* name for the filter */
2138  len=strlen(class)+30;
2139  if (instance) len+=strlen(instance);
2140  filtname=owl_malloc(len);
2141  if (!instance) {
2142    sprintf(filtname, "class-%s", class);
2143  } else {
2144    sprintf(filtname, "class-%s-instance-%s", class, instance);
2145  }
2146  /* downcase it */
2147  downstr(filtname);
2148  /* turn spaces into hyphens */
2149  owl_util_tr(filtname, ' ', '.');
2150 
2151  /* if it already exists then go with it.  This lets users override */
2152  if (owl_global_get_filter(&g, filtname)) {
2153    return(filtname);
2154  }
2155
2156  /* create the new filter */
2157  argbuff=owl_malloc(len+20);
2158  tmpclass=owl_strdup(class);
2159  owl_util_tr(tmpclass, ' ', '.');
2160  if (instance) {
2161    tmpinstance=owl_strdup(instance);
2162    owl_util_tr(tmpinstance, ' ', '.');
2163  }
2164  sprintf(argbuff, "( class ^%s$ )", tmpclass);
2165  if (tmpinstance) {
2166    sprintf(argbuff, "%s and ( instance ^%s$ )", argbuff, tmpinstance);
2167  }
2168  owl_free(tmpclass);
2169  if (tmpinstance) owl_free(tmpinstance);
2170
2171  f=owl_malloc(sizeof(owl_filter));
2172  owl_filter_init_fromstring(f, filtname, argbuff);
2173
2174  /* add it to the global list */
2175  owl_global_add_filter(&g, f);
2176
2177  owl_free(argbuff);
2178  return(filtname);
2179}
2180
2181/* Create a filter for personal zephyrs to or from the specified
2182 * zephyr user.  Includes login/logout notifications for the user.
2183 * The name of the filter will be 'user-<user>'.  If a filter already
2184 * exists with this name, no new filter will be created.  This allows
2185 * the configuration to override this function.  Returns the name of
2186 * the filter, which the caller must free.
2187 */
2188char *owl_function_zuserfilt(char *user)
2189{
2190  owl_filter *f;
2191  char *argbuff, *longuser, *shortuser, *filtname;
2192
2193  /* stick the local realm on if it's not there */
2194  longuser=long_zuser(user);
2195  shortuser=short_zuser(user);
2196
2197  /* name for the filter */
2198  filtname=owl_malloc(strlen(shortuser)+20);
2199  sprintf(filtname, "user-%s", shortuser);
2200
2201  /* if it already exists then go with it.  This lets users override */
2202  if (owl_global_get_filter(&g, filtname)) {
2203    return(owl_strdup(filtname));
2204  }
2205
2206  /* create the new-internal filter */
2207  f=owl_malloc(sizeof(owl_filter));
2208
2209  argbuff=owl_malloc(strlen(longuser)+1000);
2210  sprintf(argbuff, "( type ^zephyr$ and ( class ^message$ and instance ^personal$ and ");
2211  sprintf(argbuff, "%s ( ( direction ^in$ and sender ^%s$ ) or ( direction ^out$ and recipient ^%s$ ) ) )", argbuff, longuser, longuser);
2212  sprintf(argbuff, "%s or ( ( class ^login$ ) and ( sender ^%s$ ) ) )", argbuff, longuser);
2213
2214  owl_filter_init_fromstring(f, filtname, argbuff);
2215
2216  /* add it to the global list */
2217  owl_global_add_filter(&g, f);
2218
2219  /* free stuff */
2220  owl_free(argbuff);
2221  owl_free(longuser);
2222  owl_free(shortuser);
2223
2224  return(filtname);
2225}
2226
2227/* Create a filter for AIM IM messages to or from the specified
2228 * screenname.  The name of the filter will be 'aimuser-<user>'.  If a
2229 * filter already exists with this name, no new filter will be
2230 * created.  This allows the configuration to override this function.
2231 * Returns the name of the filter, which the caller must free.
2232 */
2233char *owl_function_aimuserfilt(char *user)
2234{
2235  owl_filter *f;
2236  char *argbuff, *filtname;
2237
2238  /* name for the filter */
2239  filtname=owl_malloc(strlen(user)+40);
2240  sprintf(filtname, "aimuser-%s", user);
2241
2242  /* if it already exists then go with it.  This lets users override */
2243  if (owl_global_get_filter(&g, filtname)) {
2244    return(owl_strdup(filtname));
2245  }
2246
2247  /* create the new-internal filter */
2248  f=owl_malloc(sizeof(owl_filter));
2249
2250  argbuff=owl_malloc(1000);
2251  sprintf(argbuff,
2252          "( type ^aim$ and ( ( sender ^%s$ and recipient ^%s$ ) or ( sender ^%s$ and recipient ^%s$ ) ) )",
2253          user, owl_global_get_aim_screenname(&g), owl_global_get_aim_screenname(&g), user);
2254
2255  owl_filter_init_fromstring(f, filtname, argbuff);
2256
2257  /* add it to the global list */
2258  owl_global_add_filter(&g, f);
2259
2260  /* free stuff */
2261  owl_free(argbuff);
2262
2263  return(filtname);
2264}
2265
2266char *owl_function_typefilt(char *type)
2267{
2268  owl_filter *f;
2269  char *argbuff, *filtname;
2270
2271  /* name for the filter */
2272  filtname=owl_sprintf("type-%s", type);
2273
2274  /* if it already exists then go with it.  This lets users override */
2275  if (owl_global_get_filter(&g, filtname)) {
2276    return filtname;
2277  }
2278
2279  /* create the new-internal filter */
2280  f=owl_malloc(sizeof(owl_filter));
2281
2282  argbuff = owl_sprintf("type ^%s$", type);
2283
2284  owl_filter_init_fromstring(f, filtname, argbuff);
2285
2286  /* add it to the global list */
2287  owl_global_add_filter(&g, f);
2288
2289  /* free stuff */
2290  owl_free(argbuff);
2291
2292  return filtname;
2293}
2294
2295/* If flag is 1, marks for deletion.  If flag is 0,
2296 * unmarks for deletion. */
2297void owl_function_delete_curview_msgs(int flag)
2298{
2299  owl_view *v;
2300  int i, j;
2301
2302  v=owl_global_get_current_view(&g);
2303  j=owl_view_get_size(v);
2304  for (i=0; i<j; i++) {
2305    if (flag == 1) {
2306      owl_message_mark_delete(owl_view_get_element(v, i));
2307    } else if (flag == 0) {
2308      owl_message_unmark_delete(owl_view_get_element(v, i));
2309    }
2310  }
2311
2312  owl_function_makemsg("%i messages marked for %sdeletion", j, flag?"":"un");
2313
2314  owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 
2315}
2316
2317/* Create a filter based on the current message.  Returns the name of
2318 * a filter or null.  The caller must free this name.
2319 *
2320 * if the curmsg is a personal zephyr return a filter name
2321 *    to the zephyr converstaion with that user.
2322 * If the curmsg is a zephyr class message, instance foo, recip *,
2323 *    return a filter name to the class, inst.
2324 * If the curmsg is a zephyr class message and type==0 then
2325 *    return a filter name for just the class.
2326 * If the curmsg is a zephyr class message and type==1 then
2327 *    return a filter name for the class and instance.
2328 * If the curmsg is a personal AIM message returna  filter
2329 *    name to the AIM conversation with that user
2330 */
2331char *owl_function_smartfilter(int type)
2332{
2333  owl_view *v;
2334  owl_message *m;
2335  char *zperson, *filtname=NULL;
2336 
2337  v=owl_global_get_current_view(&g);
2338  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
2339
2340  if (!m || owl_view_get_size(v)==0) {
2341    owl_function_makemsg("No message selected\n");
2342    return(NULL);
2343  }
2344
2345  /* very simple handling of admin messages for now */
2346  if (owl_message_is_type_admin(m)) {
2347    return(owl_function_typefilt("admin"));
2348  }
2349
2350  /* aim messages */
2351  if (owl_message_is_type_aim(m)) {
2352    if (owl_message_is_direction_in(m)) {
2353      filtname=owl_function_aimuserfilt(owl_message_get_sender(m));
2354    } else if (owl_message_is_direction_out(m)) {
2355      filtname=owl_function_aimuserfilt(owl_message_get_recipient(m));
2356    }
2357    return(filtname);
2358  }
2359
2360  /* narrow personal and login messages to the sender or recip as appropriate */
2361  if (owl_message_is_personal(m) || owl_message_is_login(m)) {
2362    if (owl_message_is_type_zephyr(m)) {
2363      if (owl_message_is_direction_in(m)) {
2364        zperson=short_zuser(owl_message_get_sender(m));
2365      } else {
2366        zperson=short_zuser(owl_message_get_recipient(m));
2367      }
2368      filtname=owl_function_zuserfilt(zperson);
2369      owl_free(zperson);
2370      return(filtname);
2371    }
2372    return(NULL);
2373  }
2374
2375  /* narrow class MESSAGE, instance foo, recip * messages to class, inst */
2376  if (!strcasecmp(owl_message_get_class(m), "message") && !owl_message_is_personal(m)) {
2377    filtname=owl_function_classinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
2378    return(filtname);
2379  }
2380
2381  /* otherwise narrow to the class */
2382  if (type==0) {
2383    filtname=owl_function_classinstfilt(owl_message_get_class(m), NULL);
2384  } else if (type==1) {
2385    filtname=owl_function_classinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
2386  }
2387  return(filtname);
2388}
2389
2390void owl_function_smartzpunt(int type)
2391{
2392  /* Starts a zpunt command based on the current class,instance pair.
2393   * If type=0, uses just class.  If type=1, uses instance as well. */
2394  owl_view *v;
2395  owl_message *m;
2396  char *cmd, *cmdprefix, *mclass, *minst;
2397 
2398  v=owl_global_get_current_view(&g);
2399  m=owl_view_get_element(v, owl_global_get_curmsg(&g));
2400
2401  if (!m || owl_view_get_size(v)==0) {
2402    owl_function_makemsg("No message selected\n");
2403    return;
2404  }
2405
2406  /* for now we skip admin messages. */
2407  if (owl_message_is_type_admin(m)
2408      || owl_message_is_login(m)
2409      || !owl_message_is_type_zephyr(m)) {
2410    owl_function_makemsg("smartzpunt doesn't support this message type.");
2411    return;
2412  }
2413
2414  mclass = owl_message_get_class(m);
2415  minst = owl_message_get_instance(m);
2416  if (!mclass || !*mclass || *mclass==' '
2417      || (!strcasecmp(mclass, "message") && !strcasecmp(minst, "personal"))
2418      || (type && (!minst || !*minst|| *minst==' '))) {
2419    owl_function_makemsg("smartzpunt can't safely do this for <%s,%s>",
2420                         mclass, minst);
2421  } else {
2422    cmdprefix = "start-command zpunt ";
2423    cmd = owl_malloc(strlen(cmdprefix)+strlen(mclass)+strlen(minst)+3);
2424    strcpy(cmd, cmdprefix);
2425    strcat(cmd, mclass);
2426    if (type) {
2427      strcat(cmd, " ");
2428      strcat(cmd, minst);
2429    } else {
2430      strcat(cmd, " *");
2431    }
2432    owl_function_command(cmd);
2433    owl_free(cmd);
2434  }
2435}
2436
2437
2438
2439void owl_function_color_current_filter(char *color)
2440{
2441  owl_filter *f;
2442  char *name;
2443
2444  name=owl_view_get_filtname(owl_global_get_current_view(&g));
2445  f=owl_global_get_filter(&g, name);
2446  if (!f) {
2447    owl_function_makemsg("Unknown filter");
2448    return;
2449  }
2450
2451  /* don't touch the all filter */
2452  if (!strcmp(name, "all")) {
2453    owl_function_makemsg("You may not change the 'all' filter.");
2454    return;
2455  }
2456
2457  /* deal with the case of trying change the filter color */
2458  owl_filter_set_color(f, owl_util_string_to_color(color));
2459  owl_global_set_needrefresh(&g);
2460  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2461}
2462
2463void owl_function_show_colors()
2464{
2465  owl_fmtext fm;
2466
2467  owl_fmtext_init_null(&fm);
2468  owl_fmtext_append_normal_color(&fm, "default\n", OWL_COLOR_DEFAULT);
2469  owl_fmtext_append_normal_color(&fm, "red\n", OWL_COLOR_RED);
2470  owl_fmtext_append_normal_color(&fm, "green\n", OWL_COLOR_GREEN);
2471  owl_fmtext_append_normal_color(&fm, "yellow\n", OWL_COLOR_YELLOW);
2472  owl_fmtext_append_normal_color(&fm, "blue\n", OWL_COLOR_BLUE);
2473  owl_fmtext_append_normal_color(&fm, "magenta\n", OWL_COLOR_MAGENTA);
2474  owl_fmtext_append_normal_color(&fm, "cyan\n", OWL_COLOR_CYAN);
2475  owl_fmtext_append_normal_color(&fm, "white\n", OWL_COLOR_WHITE);
2476
2477  owl_function_popless_fmtext(&fm);
2478  owl_fmtext_free(&fm);
2479}
2480
2481void owl_function_zpunt(char *class, char *inst, char *recip, int direction)
2482{
2483  /* add the given class, inst, recip to the punt list for filtering.
2484   *   if direction==0 then punt
2485   *   if direction==1 then unpunt */
2486  owl_filter *f;
2487  owl_list *fl;
2488  char *buff;
2489  int ret, i, j;
2490
2491  fl=owl_global_get_puntlist(&g);
2492
2493  /* first, create the filter */
2494  f=malloc(sizeof(owl_filter));
2495  buff=malloc(strlen(class)+strlen(inst)+strlen(recip)+100);
2496  if (!strcmp(recip, "*")) {
2497    sprintf(buff, "class ^%s$ and instance ^%s$", class, inst);
2498  } else {
2499    sprintf(buff, "class ^%s$ and instance ^%s$ and recipient %s", class, inst, recip);
2500  }
2501  owl_function_debugmsg("About to filter %s", buff);
2502  ret=owl_filter_init_fromstring(f, "punt-filter", buff);
2503  owl_free(buff);
2504  if (ret) {
2505    owl_function_makemsg("Error creating filter for zpunt");
2506    owl_filter_free(f);
2507    return;
2508  }
2509
2510  /* Check for an identical filter */
2511  j=owl_list_get_size(fl);
2512  for (i=0; i<j; i++) {
2513    if (owl_filter_equiv(f, owl_list_get_element(fl, i))) {
2514      /* if we're punting, then just silently bow out on this duplicate */
2515      if (direction==0) {
2516        owl_filter_free(f);
2517        return;
2518      }
2519
2520      /* if we're unpunting, then remove this filter from the puntlist */
2521      if (direction==1) {
2522        owl_filter_free(owl_list_get_element(fl, i));
2523        owl_list_remove_element(fl, i);
2524        return;
2525      }
2526    }
2527  }
2528
2529  /* If we're punting, add the filter to the global punt list */
2530  if (direction==0) {
2531    owl_list_append_element(fl, f);
2532  }
2533}
2534
2535void owl_function_activate_keymap(char *keymap)
2536{
2537  if (!owl_keyhandler_activate(owl_global_get_keyhandler(&g), keymap)) {
2538    owl_function_makemsg("Unable to activate keymap '%s'", keymap);
2539  }
2540}
2541
2542
2543void owl_function_show_keymaps()
2544{
2545  owl_list l;
2546  owl_fmtext fm;
2547  owl_keymap *km;
2548  owl_keyhandler *kh;
2549  int i, numkm;
2550  char *kmname;
2551
2552  kh = owl_global_get_keyhandler(&g);
2553  owl_fmtext_init_null(&fm);
2554  owl_fmtext_append_bold(&fm, "Keymaps:   ");
2555  owl_fmtext_append_normal(&fm, "(use 'show keymap <name>' for details)\n");
2556  owl_keyhandler_get_keymap_names(kh, &l);
2557  owl_fmtext_append_list(&fm, &l, "\n", owl_function_keymap_summary);
2558  owl_fmtext_append_normal(&fm, "\n");
2559
2560  numkm = owl_list_get_size(&l);
2561  for (i=0; i<numkm; i++) {
2562    kmname = owl_list_get_element(&l, i);
2563    km = owl_keyhandler_get_keymap(kh, kmname);
2564    owl_fmtext_append_bold(&fm, "\n\n----------------------------------------------------------------------------------------------------\n\n");
2565    owl_keymap_get_details(km, &fm);   
2566  }
2567  owl_fmtext_append_normal(&fm, "\n");
2568 
2569  owl_function_popless_fmtext(&fm);
2570  owl_keyhandler_keymap_namelist_free(&l);
2571  owl_fmtext_free(&fm);
2572}
2573
2574char *owl_function_keymap_summary(void *name)
2575{
2576  owl_keymap *km
2577    = owl_keyhandler_get_keymap(owl_global_get_keyhandler(&g), name);
2578  if (km) return owl_keymap_summary(km);
2579  else return(NULL);
2580}
2581
2582/* TODO: implement for real */
2583void owl_function_show_keymap(char *name)
2584{
2585  owl_fmtext fm;
2586  owl_keymap *km;
2587
2588  owl_fmtext_init_null(&fm);
2589  km = owl_keyhandler_get_keymap(owl_global_get_keyhandler(&g), name);
2590  if (km) {
2591    owl_keymap_get_details(km, &fm);
2592  } else {
2593    owl_fmtext_append_normal(&fm, "No such keymap...\n");
2594  } 
2595  owl_function_popless_fmtext(&fm);
2596  owl_fmtext_free(&fm);
2597}
2598
2599void owl_function_help_for_command(char *cmdname)
2600{
2601  owl_fmtext fm;
2602
2603  owl_fmtext_init_null(&fm);
2604  owl_cmd_get_help(owl_global_get_cmddict(&g), cmdname, &fm);
2605  owl_function_popless_fmtext(&fm); 
2606  owl_fmtext_free(&fm);
2607}
2608
2609void owl_function_search_start(char *string, int direction)
2610{
2611  /* direction is OWL_DIRECTION_DOWNWARDS or OWL_DIRECTION_UPWARDS */
2612  owl_global_set_search_active(&g, string);
2613  owl_function_search_helper(0, direction);
2614}
2615
2616void owl_function_search_continue(int direction)
2617{
2618  /* direction is OWL_DIRECTION_DOWNWARDS or OWL_DIRECTION_UPWARDS */
2619  owl_function_search_helper(1, direction);
2620}
2621
2622void owl_function_search_helper(int mode, int direction)
2623{
2624  /* move to a message that contains the string.  If direction is
2625   * OWL_DIRECTION_DOWNWARDS then search fowards, if direction is
2626   * OWL_DIRECTION_UPWARDS then search backwards.
2627   *
2628   * If mode==0 then it will stay on the current message if it
2629   * contains the string.
2630   */
2631
2632  owl_view *v;
2633  int viewsize, i, curmsg, start;
2634  owl_message *m;
2635
2636  v=owl_global_get_current_view(&g);
2637  viewsize=owl_view_get_size(v);
2638  curmsg=owl_global_get_curmsg(&g);
2639 
2640  if (viewsize==0) {
2641    owl_function_makemsg("No messages present");
2642    return;
2643  }
2644
2645  if (mode==0) {
2646    start=curmsg;
2647  } else if (direction==OWL_DIRECTION_DOWNWARDS) {
2648    start=curmsg+1;
2649  } else {
2650    start=curmsg-1;
2651  }
2652
2653  /* bounds check */
2654  if (start>=viewsize || start<0) {
2655    owl_function_makemsg("No further matches found");
2656    return;
2657  }
2658
2659  for (i=start; i<viewsize && i>=0;) {
2660    m=owl_view_get_element(v, i);
2661    if (owl_message_search(m, owl_global_get_search_string(&g))) {
2662      owl_global_set_curmsg(&g, i);
2663      owl_function_calculate_topmsg(direction);
2664      owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2665      if (direction==OWL_DIRECTION_DOWNWARDS) {
2666        owl_global_set_direction_downwards(&g);
2667      } else {
2668        owl_global_set_direction_upwards(&g);
2669      }
2670      return;
2671    }
2672    if (direction==OWL_DIRECTION_DOWNWARDS) {
2673      i++;
2674    } else {
2675      i--;
2676    }
2677  }
2678  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
2679  owl_function_makemsg("No matches found");
2680}
2681
2682
2683/* strips formatting from ztext and returns the unformatted text.
2684 * caller is responsible for freeing. */
2685char *owl_function_ztext_stylestrip(char *zt)
2686{
2687  owl_fmtext fm;
2688  char *plaintext;
2689
2690  owl_fmtext_init_null(&fm);
2691  owl_fmtext_append_ztext(&fm, zt);
2692  plaintext = owl_fmtext_print_plain(&fm);
2693  owl_fmtext_free(&fm);
2694  return(plaintext);
2695}
2696
2697/* Popup a buddylisting.  If file is NULL use the default .anyone */
2698void owl_function_buddylist(int aim, int zephyr, char *file)
2699{
2700  char *ourfile, *tmp, buff[LINE], *line;
2701  FILE *f;
2702  int numlocs, ret, i, j;
2703  ZLocations_t location[200];
2704  owl_fmtext fm;
2705  owl_buddylist *b;
2706
2707  owl_fmtext_init_null(&fm);
2708
2709  if (aim && owl_global_is_aimloggedin(&g)) {
2710    b=owl_global_get_buddylist(&g);
2711
2712    owl_fmtext_append_bold(&fm, "AIM users logged in:\n");
2713    j=owl_buddylist_get_size(b);
2714    for (i=0; i<j; i++) {
2715      owl_fmtext_append_normal(&fm, "  ");
2716      owl_fmtext_append_normal(&fm, owl_buddylist_get_buddy(b, i));
2717      owl_fmtext_append_normal(&fm, "\n");
2718    }
2719  }
2720
2721  if (zephyr) {
2722    if (file==NULL) {
2723      tmp=owl_global_get_homedir(&g);
2724      if (!tmp) {
2725        owl_function_makemsg("Could not determine home directory");
2726        return;
2727      }
2728      ourfile=owl_malloc(strlen(tmp)+50);
2729      sprintf(ourfile, "%s/.anyone", owl_global_get_homedir(&g));
2730    } else {
2731      ourfile=owl_strdup(file);
2732    }
2733   
2734    f=fopen(ourfile, "r");
2735    if (!f) {
2736      owl_function_makemsg("Error opening file %s: %s",
2737                           ourfile,
2738                           strerror(errno) ? strerror(errno) : "");
2739      return;
2740    }
2741   
2742    owl_fmtext_append_bold(&fm, "Zephyr users logged in:\n");
2743   
2744    while (fgets(buff, LINE, f)!=NULL) {
2745      /* ignore comments, blank lines etc. */
2746      if (buff[0]=='#') continue;
2747      if (buff[0]=='\n') continue;
2748      if (buff[0]=='\0') continue;
2749     
2750      /* strip the \n */
2751      buff[strlen(buff)-1]='\0';
2752     
2753      /* ingore from # on */
2754      tmp=strchr(buff, '#');
2755      if (tmp) tmp[0]='\0';
2756     
2757      /* ingore from SPC */
2758      tmp=strchr(buff, ' ');
2759      if (tmp) tmp[0]='\0';
2760     
2761      /* stick on the local realm. */
2762      if (!strchr(buff, '@')) {
2763        strcat(buff, "@");
2764        strcat(buff, ZGetRealm());
2765      }
2766     
2767      ret=ZLocateUser(buff, &numlocs, ZAUTH);
2768      if (ret!=ZERR_NONE) {
2769        owl_function_makemsg("Error getting location for %s", buff);
2770        continue;
2771      }
2772     
2773      numlocs=200;
2774      ret=ZGetLocations(location, &numlocs);
2775      if (ret==0) {
2776        for (i=0; i<numlocs; i++) {
2777          line=malloc(strlen(location[i].host)+strlen(location[i].time)+strlen(location[i].tty)+100);
2778          tmp=short_zuser(buff);
2779          sprintf(line, "  %-10.10s %-24.24s %-12.12s  %20.20s\n",
2780                  tmp,
2781                  location[i].host,
2782                  location[i].tty,
2783                  location[i].time);
2784          owl_fmtext_append_normal(&fm, line);
2785          owl_free(tmp);
2786        }
2787        if (numlocs>=200) {
2788          owl_fmtext_append_normal(&fm, "  Too many locations found for this user, truncating.\n");
2789        }
2790      }
2791    }
2792    fclose(f);
2793    owl_free(ourfile);
2794  }
2795 
2796  owl_function_popless_fmtext(&fm);
2797  owl_fmtext_free(&fm);
2798}
2799
2800void owl_function_dump(char *filename) 
2801{
2802  int i, j, count;
2803  owl_message *m;
2804  owl_view *v;
2805  FILE *file;
2806  /* struct stat sbuf; */
2807
2808  v=owl_global_get_current_view(&g);
2809
2810  /* in the future make it ask yes/no */
2811  /*
2812  ret=stat(filename, &sbuf);
2813  if (!ret) {
2814    ret=owl_function_askyesno("File exists, continue? [Y/n]");
2815    if (!ret) return;
2816  }
2817  */
2818
2819  file=fopen(filename, "w");
2820  if (!file) {
2821    owl_function_makemsg("Error opening file");
2822    return;
2823  }
2824
2825  count=0;
2826  j=owl_view_get_size(v);
2827  for (i=0; i<j; i++) {
2828    m=owl_view_get_element(v, i);
2829    fputs(owl_message_get_text(m), file);
2830  }
2831  fclose(file);
2832}
2833
2834
2835
2836void owl_function_do_newmsgproc(void)
2837{
2838  if (owl_global_get_newmsgproc(&g) && strcmp(owl_global_get_newmsgproc(&g), "")) {
2839    /* if there's a process out there, we need to check on it */
2840    if (owl_global_get_newmsgproc_pid(&g)) {
2841      owl_function_debugmsg("Checking on newmsgproc pid==%i", owl_global_get_newmsgproc_pid(&g));
2842      owl_function_debugmsg("Waitpid return is %i", waitpid(owl_global_get_newmsgproc_pid(&g), NULL, WNOHANG));
2843      waitpid(owl_global_get_newmsgproc_pid(&g), NULL, WNOHANG);
2844      if (waitpid(owl_global_get_newmsgproc_pid(&g), NULL, WNOHANG)==-1) {
2845        /* it exited */
2846        owl_global_set_newmsgproc_pid(&g, 0);
2847        owl_function_debugmsg("newmsgproc exited");
2848      } else {
2849        owl_function_debugmsg("newmsgproc did not exit");
2850      }
2851    }
2852   
2853    /* if it exited, fork & exec a new one */
2854    if (owl_global_get_newmsgproc_pid(&g)==0) {
2855      int i, myargc;
2856      i=fork();
2857      if (i) {
2858        /* parent set the child's pid */
2859        owl_global_set_newmsgproc_pid(&g, i);
2860        owl_function_debugmsg("I'm the parent and I started a new newmsgproc with pid %i", i);
2861      } else {
2862        /* child exec's the program */
2863        char **parsed;
2864        parsed=owl_parseline(owl_global_get_newmsgproc(&g), &myargc);
2865        if (myargc < 0) {
2866          owl_function_debugmsg("Could not parse newmsgproc '%s': unbalanced quotes?", owl_global_get_newmsgproc(&g));
2867        }
2868        if (myargc <= 0) {
2869          _exit(127);
2870        }
2871        parsed=realloc(parsed, sizeof(*parsed) * (myargc+1));
2872        parsed[myargc] = NULL;
2873       
2874        owl_function_debugmsg("About to exec \"%s\" with %d arguments", parsed[0], myargc);
2875       
2876        execvp(parsed[0], parsed);
2877       
2878       
2879        /* was there an error exec'ing? */
2880        owl_function_debugmsg("Cannot run newmsgproc '%s': cannot exec '%s': %s", 
2881                              owl_global_get_newmsgproc(&g), parsed[0], strerror(errno));
2882        _exit(127);
2883      }
2884    }
2885  }
2886}
2887
2888void owl_function_xterm_raise(void)
2889{
2890  printf("\033[5t");
2891}
2892
2893void owl_function_xterm_deiconify(void)
2894{
2895  printf("\033[1t");
2896}
Note: See TracBrowser for help on using the repository browser.