source: functions.c @ 3abf28b

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