Merge Irssi 0.8.16-rc1
[silc.git] / apps / irssi / src / perl / common / Core.xs
1 #include "module.h"
2 #include "irssi-version.h"
3 #include "core.h"
4
5 #include "pidwait.h"
6 #include "session.h"
7
8 #define DEFAULT_COMMAND_CATEGORY "Perl scripts' commands"
9
10 static void perl_signal_add_hash(int priority, SV *sv)
11 {
12         HV *hv;
13         HE *he;
14         I32 len;
15
16         if (!is_hvref(sv))
17                 croak("Usage: Irssi::signal_add(hash)");
18
19         hv = hvref(sv);
20         hv_iterinit(hv);
21         while ((he = hv_iternext(hv)) != NULL)
22                 perl_signal_add_full(hv_iterkey(he, &len), HeVAL(he), priority);
23 }
24
25 static void perl_command_bind_add_hash(int priority, SV *sv, char *category)
26 {
27         HV *hv;
28         HE *he;
29         I32 len;
30
31         hv = hvref(sv);
32         hv_iterinit(hv);
33         while ((he = hv_iternext(hv)) != NULL)
34                 perl_command_bind_to(hv_iterkey(he, &len), category, HeVAL(he), priority);
35 }
36
37 static void handle_command_bind(int priority, int items, SV *p0, SV *p1, SV *p2)
38 {
39         char *category;
40         int hash;
41
42         hash = items > 0 && is_hvref(p0);
43         if (!hash) {
44                 if (items < 2 || items > 3)
45                         croak("Usage: Irssi::command_bind(signal, func, category)");
46         } else if (items > 2)
47                 croak("Usage: Irssi::command_bind(signals_hash, category)");
48
49         if (!hash) {
50                 category = items < 3 ? DEFAULT_COMMAND_CATEGORY :
51                         (char *)SvPV(p2, PL_na);
52                 perl_command_bind_to((char *)SvPV(p0, PL_na), category, p1, priority);
53         } else {
54                 category = items < 2 ? DEFAULT_COMMAND_CATEGORY :
55                         (char *)SvPV(p1, PL_na);
56                 perl_command_bind_add_hash(priority, p0, category);
57         }
58 }
59
60 static void add_tuple(gpointer key_, gpointer value_, gpointer user_data)
61 {
62         HV *hash = user_data;
63         char *key = key_;
64         char *value = value_;
65         hv_store(hash, key, strlen(key), new_pv(value), 0);
66 }
67
68 static void wrap_signal_emit(void *signal, void **p) {
69         signal_emit(signal, 6, p[0], p[1], p[2], p[3], p[4], p[5]);
70 }
71
72 static void wrap_signal_continue(void *dummy, void **p) {
73         (void)dummy;
74         signal_continue(6, p[0], p[1], p[2], p[3], p[4], p[5]);
75 }
76
77 MODULE = Irssi::Core  PACKAGE = Irssi
78 PROTOTYPES: ENABLE
79
80 void
81 signal_emit(signal, ...)
82         char *signal
83 CODE:
84         int signal_id;
85         SV *args[SIGNAL_MAX_ARGUMENTS];
86         int n, used;
87
88         signal_id = signal_get_uniq_id(signal);
89         used = items - 1;
90         if (used > SIGNAL_MAX_ARGUMENTS) {
91                 used = SIGNAL_MAX_ARGUMENTS;
92         }
93         for (n = 0; n < used; ++n) {
94                 args[n] = ST(n + 1);
95         }
96         perl_signal_args_to_c(wrap_signal_emit, signal, signal_id, args, used);
97
98 void
99 signal_continue(...)
100 CODE:
101         SV *args[SIGNAL_MAX_ARGUMENTS];
102         int n, used;
103
104         used = items;
105         if (used > SIGNAL_MAX_ARGUMENTS) {
106                 used = SIGNAL_MAX_ARGUMENTS;
107         }
108         for (n = 0; n < used; ++n) {
109                 args[n] = ST(n);
110         }
111         perl_signal_args_to_c(wrap_signal_continue, NULL, signal_get_emitted_id(), args, used);
112
113 void
114 signal_add(...)
115 CODE:
116         if (items != 1 && items != 2)
117                 croak("Usage: Irssi::signal_add(signal, func)");
118         if (items == 2)
119                 perl_signal_add_full((char *)SvPV(ST(0),PL_na), ST(1),
120                                      SIGNAL_PRIORITY_DEFAULT);
121         else
122                 perl_signal_add_hash(SIGNAL_PRIORITY_DEFAULT, ST(0));
123
124 void
125 signal_add_first(...)
126 CODE:
127         if (items != 1 && items != 2)
128                 croak("Usage: Irssi::signal_add_first(signal, func)");
129         if (items == 2)
130                 perl_signal_add_full((char *)SvPV(ST(0),PL_na), ST(1),
131                                      SIGNAL_PRIORITY_HIGH);
132         else
133                 perl_signal_add_hash(SIGNAL_PRIORITY_HIGH, ST(0));
134
135 void
136 signal_add_last(...)
137 CODE:
138         if (items != 1 && items != 2)
139                 croak("Usage: Irssi::signal_add_last(signal, func)");
140         if (items == 2)
141                 perl_signal_add_full((char *)SvPV(ST(0),PL_na), ST(1),
142                                      SIGNAL_PRIORITY_LOW);
143         else
144                 perl_signal_add_hash(SIGNAL_PRIORITY_LOW, ST(0));
145
146 void
147 signal_add_priority(...)
148 CODE:
149         if (items != 2 && items != 3)
150                 croak("Usage: Irssi::signal_add_priority(signal, func, priority)");
151         if (items == 3)
152                 perl_signal_add_full((char *)SvPV(ST(0),PL_na), ST(1), SvIV(ST(2)));
153         else
154                 perl_signal_add_hash(SvIV(ST(0)), ST(1));
155
156 void
157 signal_register(...)
158 PREINIT:
159         HV *hv;
160         HE *he;
161         I32 len, pos;
162         const char *arr[7];
163 CODE:
164         if (items != 1 || !is_hvref(ST(0)))
165                 croak("Usage: Irssi::signal_register(hash)");
166
167         hv = hvref(ST(0));
168         hv_iterinit(hv);
169         while ((he = hv_iternext(hv)) != NULL) {
170                 const char *key = hv_iterkey(he, &len);
171                 SV *val = HeVAL(he);
172                 AV *av;
173
174                 if (!SvROK(val) || SvTYPE(SvRV(val)) != SVt_PVAV)
175                         croak("not array reference");
176
177                 av = (AV *) SvRV(val);
178                 len = av_len(av)+1;
179                 if (len > 6) len = 6;
180                 for (pos = 0; pos < len; pos++) {
181                         SV **val = av_fetch(av, pos, 0);
182                         arr[pos] = SvPV(*val, PL_na);
183                 }
184                 arr[pos] = NULL;
185                 perl_signal_register(key, arr);
186         }
187
188
189 int
190 SIGNAL_PRIORITY_LOW()
191 CODE:
192         RETVAL = SIGNAL_PRIORITY_LOW;
193 OUTPUT:
194         RETVAL
195
196 int
197 SIGNAL_PRIORITY_DEFAULT()
198 CODE:
199         RETVAL = SIGNAL_PRIORITY_DEFAULT;
200 OUTPUT:
201         RETVAL
202
203 int
204 SIGNAL_PRIORITY_HIGH()
205 CODE:
206         RETVAL = SIGNAL_PRIORITY_HIGH;
207 OUTPUT:
208         RETVAL
209
210 void
211 signal_remove(signal, func)
212         char *signal
213         SV *func
214 CODE:
215         perl_signal_remove(signal, func);
216
217 void
218 signal_stop()
219
220 void
221 signal_stop_by_name(signal)
222         char *signal
223
224 char *
225 signal_get_emitted()
226 CODE:
227         RETVAL = (char *) signal_get_emitted();
228 OUTPUT:
229         RETVAL
230
231 int
232 signal_get_emitted_id()
233
234 int
235 timeout_add(msecs, func, data)
236         int msecs
237         SV *func
238         SV *data
239 CODE:
240         if (msecs < 10) {
241                 croak("Irssi::timeout() : msecs must be >= 10");
242                 RETVAL = -1;
243         } else {
244                 RETVAL = perl_timeout_add(msecs, func, data, FALSE);
245         }
246 OUTPUT:
247         RETVAL
248
249 int
250 timeout_add_once(msecs, func, data)
251         int msecs
252         SV *func
253         SV *data
254 CODE:
255         if (msecs < 10) {
256                 croak("Irssi::timeout_once() : msecs must be >= 10");
257                 RETVAL = -1;
258         } else {
259                 RETVAL = perl_timeout_add(msecs, func, data, TRUE);
260         }
261 OUTPUT:
262         RETVAL
263
264 void
265 timeout_remove(tag)
266         int tag
267 CODE:
268         perl_source_remove(tag);
269
270
271 int
272 INPUT_READ()
273 CODE:
274         RETVAL = G_INPUT_READ;
275 OUTPUT:
276         RETVAL
277
278 int
279 INPUT_WRITE()
280 CODE:
281         RETVAL = G_INPUT_WRITE;
282 OUTPUT:
283         RETVAL
284
285 int
286 input_add(source, condition, func, data)
287         int source
288         int condition
289         SV *func
290         SV *data
291 CODE:
292         RETVAL = perl_input_add(source, condition, func, data, FALSE);
293 OUTPUT:
294         RETVAL
295
296 void
297 input_remove(tag)
298         int tag
299 CODE:
300         perl_source_remove(tag);
301
302 # maybe there's some easier way than this..? :)
303 int
304 MSGLEVEL_CRAP()
305 CODE:
306         RETVAL = MSGLEVEL_CRAP;
307 OUTPUT:
308         RETVAL
309
310 int
311 MSGLEVEL_MSGS()
312 CODE:
313         RETVAL = MSGLEVEL_MSGS;
314 OUTPUT:
315         RETVAL
316
317 int
318 MSGLEVEL_PUBLIC()
319 CODE:
320         RETVAL = MSGLEVEL_PUBLIC;
321 OUTPUT:
322         RETVAL
323
324 int
325 MSGLEVEL_NOTICES()
326 CODE:
327         RETVAL = MSGLEVEL_NOTICES;
328 OUTPUT:
329         RETVAL
330
331 int
332 MSGLEVEL_SNOTES()
333 CODE:
334         RETVAL = MSGLEVEL_SNOTES;
335 OUTPUT:
336         RETVAL
337
338 int
339 MSGLEVEL_CTCPS()
340 CODE:
341         RETVAL = MSGLEVEL_CTCPS;
342 OUTPUT:
343         RETVAL
344
345 int
346 MSGLEVEL_ACTIONS()
347 CODE:
348         RETVAL = MSGLEVEL_ACTIONS;
349 OUTPUT:
350         RETVAL
351
352 int
353 MSGLEVEL_JOINS()
354 CODE:
355         RETVAL = MSGLEVEL_JOINS;
356 OUTPUT:
357         RETVAL
358
359 int
360 MSGLEVEL_PARTS()
361 CODE:
362         RETVAL = MSGLEVEL_PARTS;
363 OUTPUT:
364         RETVAL
365
366 int
367 MSGLEVEL_QUITS()
368 CODE:
369         RETVAL = MSGLEVEL_QUITS;
370 OUTPUT:
371         RETVAL
372
373 int
374 MSGLEVEL_KICKS()
375 CODE:
376         RETVAL = MSGLEVEL_KICKS;
377 OUTPUT:
378         RETVAL
379
380 int
381 MSGLEVEL_MODES()
382 CODE:
383         RETVAL = MSGLEVEL_MODES;
384 OUTPUT:
385         RETVAL
386
387 int
388 MSGLEVEL_TOPICS()
389 CODE:
390         RETVAL = MSGLEVEL_TOPICS;
391 OUTPUT:
392         RETVAL
393
394 int
395 MSGLEVEL_WALLOPS()
396 CODE:
397         RETVAL = MSGLEVEL_WALLOPS;
398 OUTPUT:
399         RETVAL
400
401 int
402 MSGLEVEL_INVITES()
403 CODE:
404         RETVAL = MSGLEVEL_INVITES;
405 OUTPUT:
406         RETVAL
407
408 int
409 MSGLEVEL_NICKS()
410 CODE:
411         RETVAL = MSGLEVEL_NICKS;
412 OUTPUT:
413         RETVAL
414
415 int
416 MSGLEVEL_DCC()
417 CODE:
418         RETVAL = MSGLEVEL_DCC;
419 OUTPUT:
420         RETVAL
421
422 int
423 MSGLEVEL_DCCMSGS()
424 CODE:
425         RETVAL = MSGLEVEL_DCCMSGS;
426 OUTPUT:
427         RETVAL
428
429 int
430 MSGLEVEL_CLIENTNOTICE()
431 CODE:
432         RETVAL = MSGLEVEL_CLIENTNOTICE;
433 OUTPUT:
434         RETVAL
435
436 int
437 MSGLEVEL_CLIENTCRAP()
438 CODE:
439         RETVAL = MSGLEVEL_CLIENTCRAP;
440 OUTPUT:
441         RETVAL
442
443 int
444 MSGLEVEL_CLIENTERROR()
445 CODE:
446         RETVAL = MSGLEVEL_CLIENTERROR;
447 OUTPUT:
448         RETVAL
449
450 int
451 MSGLEVEL_HILIGHT()
452 CODE:
453         RETVAL = MSGLEVEL_HILIGHT;
454 OUTPUT:
455         RETVAL
456
457 int
458 MSGLEVEL_ALL()
459 CODE:
460         RETVAL = MSGLEVEL_ALL;
461 OUTPUT:
462         RETVAL
463
464 int
465 MSGLEVEL_NOHILIGHT()
466 CODE:
467         RETVAL = MSGLEVEL_NOHILIGHT;
468 OUTPUT:
469         RETVAL
470
471 int
472 MSGLEVEL_NO_ACT()
473 CODE:
474         RETVAL = MSGLEVEL_NO_ACT;
475 OUTPUT:
476         RETVAL
477
478 int
479 MSGLEVEL_NEVER()
480 CODE:
481         RETVAL = MSGLEVEL_NEVER;
482 OUTPUT:
483         RETVAL
484
485 int
486 MSGLEVEL_LASTLOG()
487 CODE:
488         RETVAL = MSGLEVEL_LASTLOG;
489 OUTPUT:
490         RETVAL
491
492 int
493 level2bits(str)
494         char *str
495 CODE:
496         RETVAL = level2bits(str, NULL);
497 OUTPUT:
498         RETVAL
499
500 void
501 bits2level(bits)
502         int bits
503 PREINIT:
504         char *ret;
505 PPCODE:
506         ret = bits2level(bits);
507         XPUSHs(sv_2mortal(new_pv(ret)));
508         g_free(ret);
509
510 int
511 combine_level(level, str)
512         int level
513         char *str
514
515 void
516 command(cmd)
517         char *cmd
518 CODE:
519         perl_command(cmd, NULL, NULL);
520
521 void
522 commands()
523 PREINIT:
524         GSList *tmp;
525 PPCODE:
526         for (tmp = commands; tmp != NULL; tmp = tmp->next) {
527                 XPUSHs(sv_2mortal(plain_bless(tmp->data, "Irssi::Command")));
528         }
529
530 void
531 command_bind_first(...)
532 CODE:
533         handle_command_bind(SIGNAL_PRIORITY_HIGH, items, ST(0), ST(1), ST(2));
534
535 void
536 command_bind(...)
537 CODE:
538         handle_command_bind(SIGNAL_PRIORITY_DEFAULT, items, ST(0), ST(1), ST(2));
539
540 void
541 command_bind_last(...)
542 CODE:
543         handle_command_bind(SIGNAL_PRIORITY_LOW, items, ST(0), ST(1), ST(2));
544
545 void
546 command_runsub(cmd, data, server, item)
547         char *cmd
548         char *data
549         Irssi::Server server
550         Irssi::Windowitem item
551 CODE:
552         perl_command_runsub(cmd, data, server, item);
553
554 void
555 command_unbind(cmd, func)
556         char *cmd
557         SV *func
558 CODE:
559         perl_command_unbind(cmd, func);
560
561 void
562 command_set_options(cmd, options)
563         char *cmd
564         char *options
565
566 void
567 command_parse_options(cmd, data)
568         char *cmd
569         char *data
570 PREINIT:
571         HV *hash;
572         GHashTable *optlist;
573         void *free_arg;
574         char *ptr;
575 PPCODE:
576         if (cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
577                            cmd, &optlist, &ptr)) {
578                 hash = newHV();
579                 g_hash_table_foreach(optlist, add_tuple, hash);
580                 XPUSHs(sv_2mortal(newRV_noinc((SV*)hash)));
581                 XPUSHs(sv_2mortal(new_pv(ptr)));
582                 cmd_params_free(free_arg);
583         } else {
584                 XPUSHs(&PL_sv_undef);
585                 XPUSHs(&PL_sv_undef);
586         }
587
588 void
589 pidwait_add(pid)
590         int pid
591
592 void 
593 pidwait_remove(pid)
594         int pid
595
596 void
597 parse_special(cmd, data="", flags=0)
598         char *cmd
599         char *data
600         int flags
601 PREINIT:
602         char *ret;
603 PPCODE:
604         ret = parse_special_string(cmd, NULL, NULL, data, NULL, flags);
605         XPUSHs(sv_2mortal(new_pv(ret)));
606         g_free_not_null(ret);
607
608 char *
609 get_irssi_dir()
610 CODE:
611         RETVAL = (char *) get_irssi_dir();
612 OUTPUT:
613         RETVAL
614
615 char *
616 get_irssi_config()
617 CODE:
618         RETVAL = (char *) get_irssi_config();
619 OUTPUT:
620         RETVAL
621
622 char *
623 get_irssi_binary()
624 CODE:
625         RETVAL = irssi_binary;
626 OUTPUT:
627         RETVAL
628
629 char *
630 version()
631 PREINIT:
632         char version[100];
633 CODE:
634         g_snprintf(version, sizeof(version), "%d.%04d",
635                    IRSSI_VERSION_DATE, IRSSI_VERSION_TIME);
636         RETVAL = version;
637 OUTPUT:
638         RETVAL
639
640 int
641 get_gui()
642 CODE:
643         RETVAL = irssi_gui;
644 OUTPUT:
645         RETVAL
646
647 int
648 IRSSI_GUI_NONE()
649 CODE:
650         RETVAL = IRSSI_GUI_NONE;
651 OUTPUT:
652         RETVAL
653
654 int
655 IRSSI_GUI_TEXT()
656 CODE:
657         RETVAL = IRSSI_GUI_TEXT;
658 OUTPUT:
659         RETVAL
660
661 int
662 IRSSI_GUI_GTK()
663 CODE:
664         RETVAL = IRSSI_GUI_GTK;
665 OUTPUT:
666         RETVAL
667
668 int
669 IRSSI_GUI_GNOME()
670 CODE:
671         RETVAL = IRSSI_GUI_GNOME;
672 OUTPUT:
673         RETVAL
674
675 int
676 IRSSI_GUI_QT()
677 CODE:
678         RETVAL = IRSSI_GUI_QT;
679 OUTPUT:
680         RETVAL
681
682 int
683 IRSSI_GUI_KDE()
684 CODE:
685         RETVAL = IRSSI_GUI_KDE;
686 OUTPUT:
687         RETVAL
688
689 #*******************************
690 MODULE = Irssi::Core    PACKAGE = Irssi::Server
691 #*******************************
692
693 void
694 parse_special(server, cmd, data="", flags=0)
695         Irssi::Server server
696         char *cmd
697         char *data
698         int flags
699 PREINIT:
700         char *ret;
701 PPCODE:
702         ret = parse_special_string(cmd, server, NULL, data, NULL, flags);
703         XPUSHs(sv_2mortal(new_pv(ret)));
704         g_free_not_null(ret);
705
706 void
707 command(server, cmd)
708         Irssi::Server server
709         char *cmd
710 CODE:
711         perl_command(cmd, server, NULL);
712
713
714 #*******************************
715 MODULE = Irssi::Core    PACKAGE = Irssi::Windowitem
716 #*******************************
717
718 void
719 parse_special(item, cmd, data="", flags=0)
720         Irssi::Windowitem item
721         char *cmd
722         char *data
723         int flags
724 PREINIT:
725         char *ret;
726 PPCODE:
727         ret = parse_special_string(cmd, item->server, item, data, NULL, flags);
728         XPUSHs(sv_2mortal(new_pv(ret)));
729         g_free_not_null(ret);
730
731 void
732 command(item, cmd)
733         Irssi::Windowitem item
734         char *cmd
735 CODE:
736         perl_command(cmd, item->server, item);
737