source: perlglue.xs @ 366558f

release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 366558f was 129e609, checked in by Nelson Elhage <nelhage@mit.edu>, 12 years ago
Use a owl_dict to store the list of filters. Cathy Zhang reported that narrowing to filters that reference other filters is significantly slower than narrowing to filters that don't. The culprit is almost certainly the linear lookup of filters by name, which we currently do on each filter evaluation. Switch to using an owl_dict, which will now do a binary search over the filter list. We could potentially get this even faster by caching the owl_filter itself inside the owl_filterelement, and invalidating it somehow on filter redefinition, but we can save that sort of cleverness for later, if necessary. We also store the filters in a linked list, in order to preserve the ability to traverse them in order, for ":show filters" and for coloring.
  • Property mode set to 100644
File size: 10.7 KB
Line 
1/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2#ifdef HAVE_LIBZEPHYR
3#include <zephyr/zephyr.h>
4#endif
5#include <EXTERN.h>
6
7#define OWL_PERL
8#include "owl.h"
9
10#define SV_IS_CODEREF(sv) (SvROK((sv)) && SvTYPE(SvRV((sv))) == SVt_PVCV)
11
12typedef char utf8;
13
14        /*************************************************************
15         * NOTE
16         *************************************************************
17         * These functions, when they are intended to be user-visible,
18         * are documented in perl/lib/BarnOwl.pm. If you add functions
19         * to this file, add the appropriate documentation there!
20         *
21         * If the function is simple enough, we simply define its
22         * entire functionality here in XS. If, however, it needs
23         * complex argument processing or something, we define a
24         * simple version here that takes arguments in as flat a
25         * manner as possible, to simplify the XS code, put it in
26         * BarnOwl::Internal::, and write a perl wrapper in BarnOwl.pm
27         * that munges the arguments as appropriate and calls the
28         * internal version.
29         */
30
31MODULE = BarnOwl                PACKAGE = BarnOwl
32
33const utf8 *
34command(cmd, ...)
35        const char *cmd
36        PREINIT:
37                char *rv = NULL;
38                const char **argv;
39                int i;
40        CODE:
41        {
42                if (items == 1) {
43                        rv = owl_function_command(cmd);
44                } else {
45                        argv = owl_malloc((items + 1) * sizeof *argv);
46                        argv[0] = cmd;
47                        for(i = 1; i < items; i++) {
48                                argv[i] = SvPV_nolen(ST(i));
49                        }
50                        rv = owl_function_command_argv(argv, items);
51                        owl_free(argv);
52                }
53                RETVAL = rv;
54        }
55        OUTPUT:
56                RETVAL
57        CLEANUP:
58                if (rv) owl_free(rv);
59
60SV *
61getcurmsg()
62        CODE:
63                RETVAL = owl_perlconfig_curmessage2hashref();
64        OUTPUT:
65                RETVAL
66
67int
68getnumcols()
69        CODE:
70                RETVAL = owl_global_get_cols(&g);
71        OUTPUT:
72                RETVAL
73               
74time_t
75getidletime()
76        CODE:
77                RETVAL = owl_global_get_idletime(&g);
78        OUTPUT:
79                RETVAL
80
81const utf8 *
82zephyr_getrealm()
83        CODE:
84                RETVAL = owl_zephyr_get_realm();
85        OUTPUT:
86                RETVAL
87
88const utf8 *
89zephyr_getsender()
90        CODE:
91                RETVAL = owl_zephyr_get_sender();
92        OUTPUT:
93                RETVAL
94
95void
96zephyr_zwrite(cmd,msg)
97        const char *cmd
98        const char *msg
99        PREINIT:
100                int i;
101        CODE:
102                i = owl_zwrite_create_and_send_from_line(cmd, msg);
103
104const utf8 *
105ztext_stylestrip(ztext)
106        const char *ztext
107        PREINIT:
108                char *rv = NULL;
109        CODE:
110                rv = owl_function_ztext_stylestrip(ztext);
111                RETVAL = rv;
112        OUTPUT:
113                RETVAL
114        CLEANUP:
115                if (rv) owl_free(rv);
116
117const utf8 *
118zephyr_smartstrip_user(in)
119        const char *in
120        PREINIT:
121                char *rv = NULL;
122        CODE:
123        {
124                rv = owl_zephyr_smartstripped_user(in);
125                RETVAL = rv;
126        }
127        OUTPUT:
128                RETVAL
129        CLEANUP:
130                owl_free(rv);
131
132const utf8 *
133zephyr_getsubs()
134        PREINIT:
135                char *rv = NULL;
136        CODE:
137                rv = owl_zephyr_getsubs();
138                RETVAL = rv;
139    OUTPUT:
140                RETVAL
141    CLEANUP:
142                if (rv) owl_free(rv);
143
144void
145queue_message(msg)
146        SV *msg
147        PREINIT:
148                owl_message *m;
149        CODE:
150        {
151                if(!SvROK(msg) || SvTYPE(SvRV(msg)) != SVt_PVHV) {
152                        croak("Usage: BarnOwl::queue_message($message)");
153                }
154
155                m = owl_perlconfig_hashref2message(msg);
156
157                owl_global_messagequeue_addmsg(&g, m);
158        }
159
160void
161admin_message(header, body)
162        const char *header
163        const char *body
164        CODE:
165        {
166                owl_function_adminmsg(header, body);           
167        }
168
169void
170start_question(line, callback)
171        const char *line
172        SV *callback
173        PREINIT:
174        CODE:
175        {
176                if(!SV_IS_CODEREF(callback))
177                        croak("Callback must be a subref");
178
179                owl_function_start_question(line);
180
181                owl_editwin_set_cbdata(owl_global_get_typwin(&g), SvREFCNT_inc(callback));
182                owl_editwin_set_callback(owl_global_get_typwin(&g), owl_perlconfig_edit_callback);
183        }
184
185void
186start_password(line, callback)
187        const char *line
188        SV *callback
189        PREINIT:
190        CODE:
191        {
192                if(!SV_IS_CODEREF(callback))
193                        croak("Callback must be a subref");
194
195                owl_function_start_password(line);
196
197                owl_editwin_set_cbdata(owl_global_get_typwin(&g), SvREFCNT_inc(callback));
198                owl_editwin_set_callback(owl_global_get_typwin(&g), owl_perlconfig_edit_callback);
199        }
200
201void
202start_edit_win(line, callback)
203        const char *line
204        SV *callback
205        CODE:
206        {
207                if(!SV_IS_CODEREF(callback))
208                        croak("Callback must be a subref");
209
210                owl_function_start_edit_win(line, owl_perlconfig_edit_callback, SvREFCNT_inc(callback));
211        }
212
213
214const char * 
215get_data_dir ()
216        CODE:
217                RETVAL = owl_get_datadir();
218        OUTPUT:
219        RETVAL
220
221const char * 
222get_config_dir ()
223        CODE:
224                RETVAL = owl_global_get_confdir(&g);
225        OUTPUT:
226        RETVAL 
227
228void
229popless_text(text) 
230        const char *text
231        CODE:
232        {
233                owl_function_popless_text(text);
234        }
235
236void
237popless_ztext(text) 
238        const char *text
239        CODE:
240        {
241                owl_fmtext fm;
242                owl_fmtext_init_null(&fm);
243                owl_fmtext_append_ztext(&fm, text);
244                owl_function_popless_fmtext(&fm);
245                owl_fmtext_free(&fm);
246        }
247
248void
249error(text) 
250        const char *text
251        CODE:
252        {
253                owl_function_error("%s", text);
254        }
255
256void
257debug(text)
258        const char *text
259        CODE:
260        {
261                owl_function_debugmsg("%s", text);
262        }
263
264void
265message(text)
266        const char *text
267        CODE:
268        {
269                owl_function_makemsg("%s", text);
270        }
271
272void
273create_style(name, object)
274     const char *name
275     SV  *object
276     PREINIT:
277                owl_style *s;
278     CODE:
279        {
280                s = owl_malloc(sizeof(owl_style));
281                owl_style_create_perl(s, name, object);
282                owl_global_add_style(&g, s);
283        }
284
285int
286getnumcolors()
287        CODE:
288                RETVAL = owl_function_get_color_count();
289        OUTPUT:
290                RETVAL
291
292void
293_remove_filter(filterName)
294        const char *filterName
295        CODE:
296        {
297                /* Don't delete the current view, or the 'all' filter */
298                if (strcmp(filterName, owl_view_get_filtname(owl_global_get_current_view(&g)))
299                    && strcmp(filterName, "all")) {
300                        owl_global_remove_filter(&g,filterName);
301                }
302        }
303
304const utf8 *
305wordwrap(in, cols)
306        const char *in
307        int cols
308        PREINIT:
309                char *rv = NULL;
310        CODE:
311                rv = owl_text_wordwrap(in, cols);
312                RETVAL = rv;   
313        OUTPUT:
314                RETVAL
315        CLEANUP:
316                if (rv)
317                        owl_free(rv);
318
319void
320remove_io_dispatch(fd)
321        int fd
322        CODE:
323        owl_select_remove_perl_io_dispatch(fd);
324
325AV*
326all_filters()
327        PREINIT:
328                owl_list fl;
329        CODE:
330        {
331                owl_list_create(&fl);
332                owl_dict_get_keys(&g.filters, &fl);
333                RETVAL = owl_new_av(&fl, (SV*(*)(const void*))owl_new_sv);
334                sv_2mortal((SV*)RETVAL);
335                owl_list_free_all(&fl, owl_free);
336        }
337        OUTPUT:
338                RETVAL
339
340AV*
341all_styles()
342        PREINIT:
343                owl_list l;
344        CODE:
345        {
346                owl_list_create(&l);
347                owl_global_get_style_names(&g, &l);
348                RETVAL = owl_new_av(&l, (SV*(*)(const void*))owl_new_sv);
349                sv_2mortal((SV*)RETVAL);
350        }
351        OUTPUT:
352                RETVAL
353        CLEANUP:
354                owl_list_free_all(&l, owl_free);
355
356
357AV*
358all_variables()
359        PREINIT:
360                owl_list l;
361        CODE:
362        {
363                owl_list_create(&l);
364                owl_dict_get_keys(owl_global_get_vardict(&g), &l);
365                RETVAL = owl_new_av(&l, (SV*(*)(const void*))owl_new_sv);
366                sv_2mortal((SV*)RETVAL);
367        }
368        OUTPUT:
369                RETVAL
370        CLEANUP:
371                owl_list_free_all(&l, owl_free);
372
373
374AV*
375all_keymaps()
376        PREINIT:
377                owl_list l;
378                const owl_keyhandler *kh;
379        CODE:
380        {
381                owl_list_create(&l);
382                kh = owl_global_get_keyhandler(&g);
383                owl_keyhandler_get_keymap_names(kh, &l);
384                RETVAL = owl_new_av(&l, (SV*(*)(const void*))owl_new_sv);
385                sv_2mortal((SV*)RETVAL);
386        }
387        OUTPUT:
388                RETVAL
389        CLEANUP:
390                owl_list_free_all(&l, owl_free);
391
392void
393redisplay()
394        CODE:
395        {
396                owl_messagelist_invalidate_formats(owl_global_get_msglist(&g));
397                owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
398                owl_mainwin_redisplay(owl_global_get_mainwin(&g));
399        }
400
401const char *
402get_zephyr_variable(name)
403        const char *name;
404        CODE:
405                RETVAL = owl_zephyr_get_variable(name);
406        OUTPUT:
407                RETVAL
408
409const utf8 *
410skiptokens(str, n)
411        const char *str;
412        int n;
413        CODE:
414                RETVAL = skiptokens(str, n);
415        OUTPUT:
416                RETVAL
417
418
419MODULE = BarnOwl                PACKAGE = BarnOwl::Zephyr
420
421int
422have_zephyr()
423        CODE:
424                RETVAL = owl_global_is_havezephyr(&g);
425        OUTPUT:
426                RETVAL
427
428MODULE = BarnOwl                PACKAGE = BarnOwl::Internal
429
430
431void
432new_command(name, func, summary, usage, description)
433        char *name
434        SV *func
435        char *summary
436        char *usage
437        char *description
438        PREINIT:
439                owl_cmd cmd;
440        CODE:
441        {
442                if(!SV_IS_CODEREF(func)) {
443                        croak("Command function must be a coderef!");
444                }
445                cmd.name = name;
446                cmd.cmd_perl = SvREFCNT_inc(func);
447                cmd.summary = summary;
448                cmd.usage = usage;
449                cmd.description = description;
450                cmd.validctx = OWL_CTX_ANY;
451                cmd.cmd_aliased_to = NULL;
452                cmd.cmd_args_fn = NULL;
453                cmd.cmd_v_fn = NULL;
454                cmd.cmd_i_fn = NULL;
455                cmd.cmd_ctxargs_fn = NULL;
456                cmd.cmd_ctxv_fn = NULL;
457                cmd.cmd_ctxi_fn = NULL;
458                owl_cmddict_add_cmd(owl_global_get_cmddict(&g), &cmd);
459           }
460
461void
462new_variable_string(name, ival, summ, desc)
463        const char * name
464        const char * ival
465        const char * summ
466        const char * desc
467        CODE:
468        owl_variable_dict_newvar_string(owl_global_get_vardict(&g),
469                                        name,
470                                        summ,
471                                        desc,
472                                        ival);
473
474void
475new_variable_int(name, ival, summ, desc)
476        const char * name
477        int ival
478        const char * summ
479        const char * desc
480        CODE:
481        owl_variable_dict_newvar_int(owl_global_get_vardict(&g),
482                                     name,
483                                     summ,
484                                     desc,
485                                     ival);
486
487void
488new_variable_bool(name, ival, summ, desc)
489        const char * name
490        int ival
491        const char * summ
492        const char * desc
493        CODE:
494        owl_variable_dict_newvar_bool(owl_global_get_vardict(&g),
495                                      name,
496                                      summ,
497                                      desc,
498                                      ival);
499
500void
501add_io_dispatch(fd, mode, cb)
502        int fd
503        int mode
504        SV * cb
505        CODE:
506        owl_select_add_perl_io_dispatch(fd, mode, SvREFCNT_inc(cb));
507
508IV
509add_timer(after, interval, cb)
510        int after
511        int interval
512        SV *cb
513        PREINIT:
514                SV *ref;
515                owl_timer *t;
516        CODE:
517                ref = sv_rvweaken(newSVsv(cb));
518                t = owl_select_add_timer(after,
519                                         interval,
520                                         owl_perlconfig_perl_timer,
521                                         owl_perlconfig_perl_timer_destroy,
522                                         ref);
523        owl_function_debugmsg("Created timer %p", t);
524        RETVAL = (IV)t;
525        OUTPUT:
526                RETVAL
527
528void
529remove_timer(timer)
530        IV timer
531        PREINIT:
532                owl_timer *t;
533        CODE:
534                t = (owl_timer*)timer;
535                owl_function_debugmsg("Freeing timer %p", t);
536                                owl_select_remove_timer(t);
537
538MODULE = BarnOwl                PACKAGE = BarnOwl::Editwin
539
540int
541replace(count, string)
542        int count;
543        const char *string;
544        CODE:
545                RETVAL = owl_editwin_replace(owl_global_get_typwin(&g), count, string);
546        OUTPUT:
547                RETVAL
548
549int
550point_move(delta)
551        int delta;
552        CODE:
553                RETVAL = owl_editwin_point_move(owl_global_get_typwin(&g), delta);
554        OUTPUT:
555                RETVAL
556
557int
558replace_region(string)
559        const char *string;
560        CODE:
561                RETVAL = owl_editwin_replace_region(owl_global_get_typwin(&g), string);
562        OUTPUT:
563                RETVAL
564
565const utf8 *
566get_region()
567        PREINIT:
568                char *region;
569        CODE:
570                region = owl_editwin_get_region(owl_global_get_typwin(&g));
571                RETVAL = region;
572        OUTPUT:
573                RETVAL
574        CLEANUP:
575                owl_free(region);
576
577SV *
578save_excursion(sub)
579        SV *sub;
580        PROTOTYPE: &
581        PREINIT:
582                int count;
583                owl_editwin_excursion *x;
584        CODE:
585        {
586                x = owl_editwin_begin_excursion(owl_global_get_typwin(&g));
587                PUSHMARK(SP);
588                count = call_sv(sub, G_SCALAR|G_EVAL|G_NOARGS);
589                SPAGAIN;
590                owl_editwin_end_excursion(owl_global_get_typwin(&g), x);
591
592                if(SvTRUE(ERRSV)) {
593                        croak(NULL);
594                }
595
596                if(count == 1)
597                        RETVAL = SvREFCNT_inc(POPs);
598                else
599                        XSRETURN_UNDEF;
600
601        }
602        OUTPUT:
603                RETVAL
604
605int
606current_column()
607        CODE:
608                RETVAL = owl_editwin_current_column(owl_global_get_typwin(&g));
609        OUTPUT:
610                RETVAL
611
612int
613point()
614        CODE:
615                RETVAL = owl_editwin_get_point(owl_global_get_typwin(&g));
616        OUTPUT:
617                RETVAL
618
619int
620mark()
621        CODE:
622                RETVAL = owl_editwin_get_mark(owl_global_get_typwin(&g));
623        OUTPUT:
624                RETVAL
Note: See TracBrowser for help on using the repository browser.