ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvtperl.xs
Revision: 1.261
Committed: Tue Jul 25 18:06:07 2023 UTC (9 months, 1 week ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.260: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*----------------------------------------------------------------------*
2     * File: rxvtperl.xs
3     *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6 sf-exg 1.235 * Copyright (c) 2005-2014 Marc Lehmann <schmorp@schmorp.de>
7 root 1.1 *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10 root 1.224 * the Free Software Foundation; either version 3 of the License, or
11 root 1.1 * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21     *----------------------------------------------------------------------*/
22    
23     #define line_t perl_line_t
24     #include <EXTERN.h>
25     #include <perl.h>
26     #include <XSUB.h>
27     #undef line_t
28 root 1.151 #undef bool // perl defines it's own bool type, except with g++... what a trap
29 root 1.1
30     #include "../config.h"
31    
32 sf-exg 1.152 #include <stddef.h>
33     #include <stdarg.h>
34 root 1.1
35 root 1.257 #include <unistd.h>
36    
37     #include <X11/extensions/shape.h>
38    
39     // support old includes (https://bugs.freedesktop.org/show_bug.cgi?id=2799, https://lists.x.org/archives/xorg-arch/2005-March/000004.html)
40     #ifndef ShapeInput
41     # define ShapeInput 2
42     #endif
43 root 1.59
44 root 1.116 #include "ev_cpp.h"
45 root 1.1 #include "rxvt.h"
46 root 1.50 #include "keyboard.h"
47 root 1.1 #include "rxvtutil.h"
48     #include "rxvtperl.h"
49    
50     #include "perlxsi.c"
51    
52 ayin 1.121 #define GRAB_CURSOR THIS->scrollBar.leftptr_cursor
53 root 1.41
54 root 1.8 #undef LINENO
55     #define LINENO(n) MOD (THIS->term_start + int(n), THIS->total_rows)
56     #undef ROW
57     #define ROW(n) THIS->row_buf [LINENO (n)]
58    
59 root 1.1 /////////////////////////////////////////////////////////////////////////////
60    
61 root 1.155 typedef char * octet_string;
62     typedef char * utf8_string;
63    
64 root 1.167 typedef int render_repeat_mode;
65    
66 sf-exg 1.188 #if HAVE_PIXBUF
67 root 1.155 typedef GdkPixbuf * urxvt__pixbuf;
68 sf-exg 1.188 #endif
69 sf-exg 1.207 #if HAVE_IMG
70 root 1.155 typedef rxvt_img * urxvt__img;
71 root 1.197 typedef rxvt_img::nv rxvt_img__nv;
72 root 1.155
73     /////////////////////////////////////////////////////////////////////////////
74    
75 root 1.194 static rgba
76     parse_rgba (SV *sv, rxvt_screen *s = 0)
77 root 1.156 {
78 root 1.194 rgba c;
79    
80 root 1.198 if (SvROK (sv))
81 root 1.194 {
82 root 1.198 AV *av = (AV *)SvRV (sv);
83    
84 root 1.194 if (SvTYPE ((SV *)av) != SVt_PVAV)
85     croak ("colour must be either a colour string, or an array,");
86    
87     int len = av_len (av) + 1;
88    
89     if (len != 1 && len != 3 && len != 4)
90     croak ("component colour array must have 1, 3 or 4 components,");
91    
92     c.a = rgba::MAX_CC;
93    
94 root 1.246 c.r = c.g = c.b = float_to_component (SvNV (*av_fetch (av, 0, 0)));
95 root 1.194
96     if (len >= 3)
97     {
98 root 1.246 c.g = float_to_component (SvNV (*av_fetch (av, 1, 0)));
99     c.b = float_to_component (SvNV (*av_fetch (av, 2, 0)));
100 root 1.194
101     if (len >= 4)
102 root 1.246 c.a = float_to_component (SvNV (*av_fetch (av, 3, 0)));
103 root 1.194 }
104     }
105     else if (s)
106     {
107     rxvt_color rc;
108     rc.set (s, SvPVbyte_nolen (sv));
109     rc.get (c);
110     }
111 root 1.195 else
112     croak ("unable to parse colour,");
113 root 1.194
114     return c;
115 root 1.156 }
116    
117     /////////////////////////////////////////////////////////////////////////////
118 sf-exg 1.207 #endif
119 root 1.156
120 root 1.1 static wchar_t *
121     sv2wcs (SV *sv)
122     {
123     STRLEN len;
124     char *str = SvPVutf8 (sv, len);
125     return rxvt_utf8towcs (str, len);
126     }
127    
128     static SV *
129 root 1.25 wcs2sv (wchar_t *wstr, int len = -1)
130     {
131     char *str = rxvt_wcstoutf8 (wstr, len);
132    
133     SV *sv = newSVpv (str, 0);
134     SvUTF8_on (sv);
135     free (str);
136    
137     return sv;
138     }
139    
140     static SV *
141 root 1.1 newSVptr (void *ptr, const char *klass)
142     {
143     HV *hv = newHV ();
144 root 1.18 sv_magic ((SV *)hv, 0, PERL_MAGIC_ext, (char *)ptr, 0);
145 root 1.1 return sv_bless (newRV_noinc ((SV *)hv), gv_stashpv (klass, 1));
146     }
147    
148 root 1.18 static void
149     clearSVptr (SV *sv)
150     {
151     if (SvROK (sv))
152     sv = SvRV (sv);
153    
154     hv_clear ((HV *)sv);
155     sv_unmagic (sv, PERL_MAGIC_ext);
156     }
157    
158 root 1.1 static long
159     SvPTR (SV *sv, const char *klass)
160     {
161     if (!sv_derived_from (sv, klass))
162     croak ("object of type %s expected", klass);
163    
164 root 1.18 MAGIC *mg = mg_find (SvRV (sv), PERL_MAGIC_ext);
165 root 1.1
166 root 1.18 if (!mg)
167 root 1.1 croak ("perl code used %s object, but C++ object is already destroyed, caught", klass);
168    
169 root 1.18 return (long)mg->mg_ptr;
170 root 1.1 }
171    
172 root 1.95 #define newSVterm(term) SvREFCNT_inc ((SV *)(term)->perl.self)
173     #define SvTERM(sv) (rxvt_term *)SvPTR ((sv), "urxvt::term")
174 root 1.1
175     /////////////////////////////////////////////////////////////////////////////
176    
177 root 1.13 #define SvOVERLAY(sv) (overlay *)SvPTR (sv, "urxvt::overlay")
178    
179 root 1.126 class overlay : overlay_base
180     {
181 root 1.13 rxvt_term *THIS;
182 root 1.93 AV *overlay_av;
183 root 1.13 int border;
184    
185 root 1.93 public:
186     HV *self;
187    
188 root 1.13 overlay (rxvt_term *THIS, int x_, int y_, int w_, int h_, rend_t rstyle, int border);
189     ~overlay ();
190    
191 root 1.18 void show ();
192     void hide ();
193    
194 root 1.13 void swap ();
195    
196     void set (int x, int y, SV *str, SV *rend);
197     };
198    
199     overlay::overlay (rxvt_term *THIS, int x_, int y_, int w_, int h_, rend_t rstyle, int border)
200 root 1.126 : THIS(THIS), border(border == 2), overlay_av (0)
201 root 1.13 {
202 root 1.126 x = x_;
203     y = y_;
204     w = w_;
205     h = h_;
206    
207 root 1.103 if (w < 0) w = 0;
208     if (h < 0) h = 0;
209    
210 root 1.13 if (border == 2)
211     {
212     w += 2;
213     h += 2;
214     }
215    
216     text = new text_t *[h];
217     rend = new rend_t *[h];
218 root 1.24
219 root 1.13 for (int y = 0; y < h; y++)
220 root 1.24 {
221 root 1.13 text_t *tp = text[y] = new text_t[w];
222     rend_t *rp = rend[y] = new rend_t[w];
223 root 1.24
224 root 1.13 text_t t0, t1, t2;
225     rend_t r = rstyle;
226 root 1.24
227 root 1.13 if (border == 2)
228     {
229     if (y == 0)
230     t0 = 0x2554, t1 = 0x2550, t2 = 0x2557;
231     else if (y < h - 1)
232     t0 = 0x2551, t1 = 0x0020, t2 = 0x2551;
233     else
234     t0 = 0x255a, t1 = 0x2550, t2 = 0x255d;
235 root 1.24
236     *tp++ = t0;
237 root 1.13 *rp++ = r;
238 root 1.24
239 root 1.13 for (int x = w - 2; x-- > 0; )
240     {
241     *tp++ = t1;
242     *rp++ = r;
243 root 1.24 }
244 root 1.13
245     *tp = t2;
246 root 1.24 *rp = r;
247 root 1.13 }
248     else
249     for (int x = w; x-- > 0; )
250     {
251     *tp++ = 0x0020;
252     *rp++ = r;
253 root 1.24 }
254     }
255 root 1.13
256 root 1.18 show ();
257 root 1.13 }
258    
259     overlay::~overlay ()
260     {
261 root 1.18 hide ();
262    
263 root 1.13 for (int y = h; y--; )
264     {
265     delete [] text[y];
266     delete [] rend[y];
267     }
268    
269     delete [] text;
270     delete [] rend;
271     }
272    
273 root 1.18 void
274     overlay::show ()
275     {
276 root 1.93 if (overlay_av)
277 root 1.76 return;
278    
279 root 1.93 overlay_av = (AV *)SvREFCNT_inc (SvRV (
280     *hv_fetch ((HV *)SvRV ((SV *)THIS->perl.self), "_overlay", 8, 0)
281     ));
282     av_push (overlay_av, newSViv ((long)this));
283 root 1.18
284 root 1.93 THIS->want_refresh = 1;
285 root 1.118 THIS->refresh_check ();
286 root 1.18 }
287    
288     void
289     overlay::hide ()
290     {
291 root 1.93 if (!overlay_av)
292 root 1.76 return;
293    
294     int i;
295 root 1.18
296 root 1.93 for (i = AvFILL (overlay_av); i >= 0; i--)
297     if (SvIV (*av_fetch (overlay_av, i, 1)) == (long)this)
298 root 1.101 break;
299 root 1.76
300 root 1.93 for (; i < AvFILL (overlay_av); i++)
301     av_store (overlay_av, i, SvREFCNT_inc (*av_fetch (overlay_av, i + 1, 0)));
302    
303 sf-exg 1.239 SvREFCNT_dec (av_pop (overlay_av));
304 root 1.18
305 root 1.93 SvREFCNT_dec (overlay_av);
306     overlay_av = 0;
307    
308     THIS->want_refresh = 1;
309 root 1.118 THIS->refresh_check ();
310 root 1.18 }
311    
312 root 1.13 void overlay::swap ()
313     {
314     int ov_x = max (0, min (MOD (x, THIS->ncol), THIS->ncol - w));
315     int ov_y = max (0, min (MOD (y, THIS->nrow), THIS->nrow - h));
316    
317     int ov_w = min (w, THIS->ncol - ov_x);
318     int ov_h = min (h, THIS->nrow - ov_y);
319    
320 root 1.126 // hide cursor if it is within the overlay area
321     if (IN_RANGE_EXC (THIS->screen.cur.col - ov_x, 0, ov_w)
322     && IN_RANGE_EXC (THIS->screen.cur.row - ov_y, 0, ov_h))
323     THIS->screen.flags &= ~Screen_VisibleCursor;
324    
325 root 1.13 for (int y = ov_h; y--; )
326     {
327     text_t *t1 = text [y];
328     rend_t *r1 = rend [y];
329 root 1.24
330 root 1.67 text_t *t2 = ROW(y + ov_y + THIS->view_start).t + ov_x;
331     rend_t *r2 = ROW(y + ov_y + THIS->view_start).r + ov_x;
332 root 1.13
333     for (int x = ov_w; x--; )
334 root 1.24 {
335 root 1.13 text_t t = *t1; *t1++ = *t2; *t2++ = t;
336     rend_t r = *r1; *r1++ = *r2; *r2++ = SET_FONT (r, THIS->fontset [GET_STYLE (r)]->find_font (t));
337     }
338     }
339    
340     }
341    
342 root 1.14 void overlay::set (int x, int y, SV *text, SV *rend)
343 root 1.13 {
344     x += border;
345     y += border;
346    
347     if (!IN_RANGE_EXC (y, 0, h - border))
348     return;
349    
350 root 1.14 wchar_t *wtext = sv2wcs (text);
351 root 1.13
352 root 1.14 for (int col = min (wcslen (wtext), w - x - border); col--; )
353     this->text [y][x + col] = wtext [col];
354 root 1.24
355 root 1.14 free (wtext);
356    
357     if (rend)
358     {
359     if (!SvROK (rend) || SvTYPE (SvRV (rend)) != SVt_PVAV)
360     croak ("rend must be arrayref");
361    
362     AV *av = (AV *)SvRV (rend);
363    
364 root 1.76 for (int col = min (AvFILL (av) + 1, w - x - border); col--; )
365 root 1.14 this->rend [y][x + col] = SvIV (*av_fetch (av, col, 1));
366     }
367 root 1.13
368     THIS->want_refresh = 1;
369 root 1.118 THIS->refresh_check ();
370 root 1.13 }
371    
372 root 1.109 /////////////////////////////////////////////////////////////////////////////
373    
374 ayin 1.119 #include "iom_perl.h"
375 root 1.13
376     /////////////////////////////////////////////////////////////////////////////
377    
378 root 1.1 struct rxvt_perl_interp rxvt_perl;
379    
380     static PerlInterpreter *perl;
381    
382 root 1.247 #if 0 /* we are not a library anymore, so doing this is just not worth it */
383     /*THINK/TODO: this has the side effect of, of course, not calling destructors. */
384 root 1.261 /* but these are not guaranteed anyway... */
385 root 1.1 rxvt_perl_interp::~rxvt_perl_interp ()
386     {
387     if (perl)
388     {
389 root 1.249 localise_env set_environ (perl_environ);
390 root 1.1 perl_destruct (perl);
391     perl_free (perl);
392 root 1.125 PERL_SYS_TERM ();
393 root 1.1 }
394     }
395 root 1.247 #endif
396 root 1.1
397     void
398 root 1.192 rxvt_perl_interp::init ()
399 root 1.1 {
400     if (!perl)
401     {
402 root 1.260 rxvt_push_locale ("C"); // perl init destroys current locale
403 root 1.68
404 root 1.134 {
405     perl_environ = rxvt_environ;
406     localise_env set_environ (perl_environ);
407 root 1.56
408 root 1.244 const char *args[] = {
409 root 1.134 "",
410     "-e"
411     "BEGIN {"
412     " urxvt->bootstrap;"
413     " unshift @INC, '" LIBDIR "';"
414     "}"
415     ""
416 root 1.243 "use urxvt;",
417     0
418 root 1.134 };
419 root 1.243 int argc = ecb_array_length (args) - 1;
420 root 1.244 char **argv = (char **)args;
421 root 1.1
422 root 1.134 PERL_SYS_INIT3 (&argc, &argv, &environ);
423     perl = perl_alloc ();
424     perl_construct (perl);
425 root 1.1
426 root 1.134 if (perl_parse (perl, xs_init, argc, argv, (char **)NULL)
427     || perl_run (perl))
428     {
429     rxvt_warn ("unable to initialize perl-interpreter, continuing without.\n");
430 root 1.57
431 root 1.134 perl_destruct (perl);
432     perl_free (perl);
433     perl = 0;
434     }
435     }
436 root 1.68
437     rxvt_pop_locale ();
438 root 1.1 }
439 root 1.192 }
440    
441     void
442     rxvt_perl_interp::init (rxvt_term *term)
443     {
444     init ();
445 root 1.68
446 root 1.182 if (perl && !term->perl.self)
447 root 1.70 {
448     // runs outside of perls ENV
449     term->perl.self = (void *)newSVptr ((void *)term, "urxvt::term");
450 root 1.76 hv_store ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, newRV_noinc ((SV *)newAV ()), 0);
451 sf-exg 1.142 hv_store ((HV *)SvRV ((SV *)term->perl.self), "_selection", 10, newRV_noinc ((SV *)newAV ()), 0);
452 root 1.70 }
453 root 1.1 }
454    
455 root 1.170 void
456 root 1.192 rxvt_perl_interp::eval (const char *str)
457     {
458     eval_pv (str, 1);
459     }
460    
461     void
462 root 1.171 rxvt_perl_interp::usage (rxvt_term *term, int type)
463 root 1.170 {
464     localise_env set_environ (perl_environ);
465    
466     ENTER;
467     SAVETMPS;
468    
469     dSP;
470 root 1.174 PUSHMARK (SP);
471 root 1.171 EXTEND (SP, 2);
472     PUSHs (sv_2mortal (newSVterm (term)));
473     PUSHs (sv_2mortal (newSViv (type)));
474 root 1.170 PUTBACK;
475 root 1.173 call_pv ("urxvt::usage", G_VOID | G_DISCARD);
476 root 1.170
477     FREETMPS;
478     LEAVE;
479     }
480    
481     uint8_t
482 root 1.173 rxvt_perl_interp::parse_resource (rxvt_term *term, const char *name, bool arg, bool longopt, bool flag, const char *value)
483 root 1.170 {
484     localise_env set_environ (perl_environ);
485    
486     ENTER;
487     SAVETMPS;
488    
489     dSP;
490 root 1.174 PUSHMARK (SP);
491 root 1.170 EXTEND (SP, 6);
492     PUSHs (sv_2mortal (newSVterm (term)));
493     PUSHs (sv_2mortal (newSVpv (name, 0)));
494     PUSHs (arg ? &PL_sv_yes : &PL_sv_no);
495     PUSHs (longopt ? &PL_sv_yes : &PL_sv_no);
496     PUSHs (flag ? &PL_sv_yes : &PL_sv_no);
497     PUSHs (value ? sv_2mortal (newSVpv (value, 0)) : &PL_sv_undef);
498     PUTBACK;
499 root 1.173 call_pv ("urxvt::parse_resource", G_SCALAR);
500     SPAGAIN;
501 root 1.170
502     uint8_t ret = POPi;
503    
504     FREETMPS;
505     LEAVE;
506    
507     return ret;
508     }
509    
510 root 1.45 static void
511 root 1.223 _keysym_resource_push (rxvt_term *term, const char *k, const char *v)
512     {
513 sf-exg 1.227 unsigned int state;
514    
515     if (term->parse_keysym (k, state) == -1)
516     return;
517    
518 root 1.223 dSP;
519     XPUSHs (sv_2mortal (newSVpv (v, 0)));
520     PUTBACK;
521     }
522    
523     static void
524     _keysym_resources (rxvt_term *term)
525     {
526     term->enumerate_keysym_resources (_keysym_resource_push);
527     }
528    
529     static void
530 root 1.45 ungrab (rxvt_term *THIS)
531     {
532     if (THIS->perl.grabtime)
533     {
534 root 1.96 XUngrabKeyboard (THIS->dpy, THIS->perl.grabtime);
535     XUngrabPointer (THIS->dpy, THIS->perl.grabtime);
536 root 1.45 THIS->perl.grabtime = 0;
537     }
538     }
539    
540 root 1.1 bool
541 root 1.255 rxvt_perl_interp::invoke (rxvt_term *term, int htype, ...)
542 root 1.1 {
543 root 1.68 if (!perl || !term->perl.self)
544 root 1.1 return false;
545 root 1.24
546 root 1.134 localise_env set_environ (perl_environ);
547    
548 root 1.68 // pre-handling of some events
549     if (htype == HOOK_REFRESH_END)
550 root 1.76 {
551     AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, 0));
552 ayin 1.115
553 root 1.76 for (int i = 0; i <= AvFILL (av); i++)
554     ((overlay *)SvIV (*av_fetch (av, i, 0)))->swap ();
555     }
556 sf-exg 1.142 else if (htype == HOOK_DESTROY)
557     {
558     AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_selection", 10, 0));
559    
560     for (int i = AvFILL (av); i >= 0; i--)
561     {
562     rxvt_selection *req = (rxvt_selection *)SvIV (*av_fetch (av, i, 0));
563     delete req;
564     }
565     }
566 root 1.1
567 root 1.68 bool event_consumed;
568 root 1.1
569 root 1.170 if (term->perl.should_invoke [htype])
570 root 1.134 {
571     dSP;
572     va_list ap;
573    
574     va_start (ap, htype);
575 root 1.1
576 root 1.134 ENTER;
577     SAVETMPS;
578 root 1.1
579 root 1.134 PUSHMARK (SP);
580 root 1.1
581 root 1.138 EXTEND (SP, 2);
582     PUSHs (sv_2mortal (newSVterm (term)));
583     PUSHs (sv_2mortal (newSViv (htype)));
584 root 1.1
585 root 1.134 for (;;) {
586     data_type dt = (data_type)va_arg (ap, int);
587 root 1.1
588 root 1.134 switch (dt)
589     {
590     case DT_INT:
591     XPUSHs (sv_2mortal (newSViv (va_arg (ap, int))));
592     break;
593 root 1.1
594 root 1.134 case DT_LONG:
595     XPUSHs (sv_2mortal (newSViv (va_arg (ap, long))));
596     break;
597 root 1.68
598 root 1.134 case DT_STR:
599     XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
600     break;
601 root 1.68
602 root 1.134 case DT_STR_LEN:
603     {
604     char *str = va_arg (ap, char *);
605     int len = va_arg (ap, int);
606 root 1.68
607 root 1.134 XPUSHs (sv_2mortal (newSVpvn (str, len)));
608     }
609     break;
610 root 1.68
611 root 1.134 case DT_WCS_LEN:
612     {
613     wchar_t *wstr = va_arg (ap, wchar_t *);
614     int wlen = va_arg (ap, int);
615 root 1.68
616 root 1.134 XPUSHs (sv_2mortal (wcs2sv (wstr, wlen)));
617     }
618     break;
619 root 1.68
620 root 1.134 case DT_LCS_LEN:
621     {
622     long *lstr = va_arg (ap, long *);
623     int llen = va_arg (ap, int);
624 root 1.68
625 root 1.134 XPUSHs (sv_2mortal (newSVpvn ((char *)lstr, llen * sizeof (long))));
626     }
627     break;
628 root 1.91
629 root 1.134 case DT_XEVENT:
630     {
631     XEvent *xe = va_arg (ap, XEvent *);
632     HV *hv = newHV ();
633 root 1.91
634 root 1.134 # define set(name, sv) hv_store (hv, # name, sizeof (# name) - 1, sv, 0)
635     # define setiv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSViv (val), 0)
636     # define setuv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSVuv (val), 0)
637     # undef set
638    
639     setiv (type, xe->type);
640     setiv (send_event, xe->xany.send_event);
641     setiv (serial, xe->xany.serial);
642 root 1.29
643 root 1.134 switch (xe->type)
644     {
645     case KeyPress:
646     case KeyRelease:
647     case ButtonPress:
648     case ButtonRelease:
649     case MotionNotify:
650     setuv (window, xe->xmotion.window);
651     setuv (root, xe->xmotion.root);
652     setuv (subwindow, xe->xmotion.subwindow);
653     setuv (time, xe->xmotion.time);
654     setiv (x, xe->xmotion.x);
655     setiv (y, xe->xmotion.y);
656     setiv (row, xe->xmotion.y / term->fheight + term->view_start);
657     setiv (col, xe->xmotion.x / term->fwidth);
658     setiv (x_root, xe->xmotion.x_root);
659     setiv (y_root, xe->xmotion.y_root);
660     setuv (state, xe->xmotion.state);
661    
662     switch (xe->type)
663     {
664     case KeyPress:
665     case KeyRelease:
666     setuv (keycode, xe->xkey.keycode);
667     break;
668    
669     case ButtonPress:
670     case ButtonRelease:
671     setuv (button, xe->xbutton.button);
672     break;
673    
674     case MotionNotify:
675     setiv (is_hint, xe->xmotion.is_hint);
676     break;
677     }
678    
679     break;
680    
681     case MapNotify:
682     case UnmapNotify:
683     case ConfigureNotify:
684     setuv (event, xe->xconfigure.event);
685     setuv (window, xe->xconfigure.window);
686    
687     switch (xe->type)
688     {
689     case ConfigureNotify:
690     setiv (x, xe->xconfigure.x);
691     setiv (y, xe->xconfigure.y);
692     setiv (width, xe->xconfigure.width);
693     setiv (height, xe->xconfigure.height);
694     setuv (above, xe->xconfigure.above);
695     break;
696     }
697    
698     break;
699    
700     case PropertyNotify:
701     setuv (window, xe->xproperty.window);
702     setuv (atom, xe->xproperty.atom);
703     setuv (time, xe->xproperty.time);
704     setiv (state, xe->xproperty.state);
705     break;
706    
707     case ClientMessage:
708     setuv (window, xe->xclient.window);
709     setuv (message_type, xe->xclient.message_type);
710     setuv (format, xe->xclient.format);
711     setuv (l0, xe->xclient.data.l[0]);
712     setuv (l1, xe->xclient.data.l[1]);
713     setuv (l2, xe->xclient.data.l[2]);
714     setuv (l3, xe->xclient.data.l[3]);
715     setuv (l4, xe->xclient.data.l[4]);
716     break;
717     }
718 root 1.68
719 root 1.134 XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
720     }
721     break;
722 root 1.68
723 root 1.134 case DT_END:
724     goto call;
725 root 1.68
726 root 1.134 default:
727     rxvt_fatal ("FATAL: unable to pass data type %d\n", dt);
728     }
729     }
730 root 1.29
731 root 1.134 call:
732     va_end (ap);
733 root 1.29
734 root 1.134 PUTBACK;
735     int count = call_pv ("urxvt::invoke", G_ARRAY | G_EVAL);
736     SPAGAIN;
737 root 1.29
738 root 1.134 if (count)
739     {
740     SV *status = POPs;
741     count = SvTRUE (status);
742     }
743 root 1.29
744 root 1.134 PUTBACK;
745     FREETMPS;
746     LEAVE;
747 root 1.29
748 root 1.134 if (SvTRUE (ERRSV))
749     {
750 root 1.138 rxvt_warn ("perl hook %d evaluation error: %s", htype, SvPVbyte_nolen (ERRSV));
751 root 1.134 ungrab (term); // better lose the grab than the session
752     }
753 root 1.68
754 root 1.134 event_consumed = !!count;
755     }
756 root 1.68 else
757     event_consumed = false;
758    
759     // post-handling of some events
760     if (htype == HOOK_REFRESH_BEGIN)
761 root 1.76 {
762     AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, 0));
763 ayin 1.115
764 root 1.76 for (int i = AvFILL (av); i >= 0; i--)
765     ((overlay *)SvIV (*av_fetch (av, i, 0)))->swap ();
766     }
767 root 1.68 else if (htype == HOOK_DESTROY)
768 root 1.57 {
769 root 1.68 clearSVptr ((SV *)term->perl.self);
770     SvREFCNT_dec ((SV *)term->perl.self);
771 ayin 1.115
772 root 1.91 // don't allow further calls
773     term->perl.self = 0;
774 root 1.57 }
775 root 1.68
776     return event_consumed;
777 root 1.1 }
778    
779 root 1.138 void
780     rxvt_perl_interp::selection_finish (rxvt_selection *sel, char *data, unsigned int len)
781     {
782     localise_env set_environ (perl_environ);
783    
784     ENTER;
785     SAVETMPS;
786    
787     dSP;
788     XPUSHs (sv_2mortal (newSVpvn (data, len)));
789 root 1.170 PUTBACK;
790 root 1.138 call_sv ((SV *)sel->cb_sv, G_VOID | G_DISCARD | G_EVAL);
791    
792     if (SvTRUE (ERRSV))
793     rxvt_warn ("perl selection callback evaluation error: %s", SvPVbyte_nolen (ERRSV));
794    
795     FREETMPS;
796     LEAVE;
797     }
798    
799 root 1.1 /////////////////////////////////////////////////////////////////////////////
800    
801     MODULE = urxvt PACKAGE = urxvt
802    
803     PROTOTYPES: ENABLE
804    
805     BOOT:
806     {
807 root 1.52 sv_setsv (get_sv ("urxvt::LIBDIR", 1), newSVpvn (LIBDIR, sizeof (LIBDIR) - 1));
808     sv_setsv (get_sv ("urxvt::RESNAME", 1), newSVpvn (RESNAME, sizeof (RESNAME) - 1));
809     sv_setsv (get_sv ("urxvt::RESCLASS", 1), newSVpvn (RESCLASS, sizeof (RESCLASS) - 1));
810     sv_setsv (get_sv ("urxvt::RXVTNAME", 1), newSVpvn (RXVTNAME, sizeof (RXVTNAME) - 1));
811 root 1.37
812 root 1.1 AV *hookname = get_av ("urxvt::HOOKNAME", 1);
813 root 1.21 # define def(sym) av_store (hookname, HOOK_ ## sym, newSVpv (# sym, 0));
814     # include "hookinc.h"
815     # undef def
816 root 1.1
817 root 1.39 HV *option = get_hv ("urxvt::OPTION", 1);
818 root 1.133 # define def(name) hv_store (option, # name, sizeof (# name) - 1, newSVuv (Opt_ ## name), 0);
819 root 1.39 # define nodef(name)
820     # include "optinc.h"
821     # undef nodef
822     # undef def
823    
824     HV *stash = gv_stashpv ("urxvt", 1);
825 root 1.97 static const struct {
826 root 1.62 const char *name;
827     IV iv;
828     } *civ, const_iv[] = {
829     # define const_iv(name) { # name, (IV)name }
830 root 1.218 const_iv (HOOK_INIT),
831     const_iv (HOOK_DESTROY),
832 root 1.222 const_iv (HOOK_ACTION),
833 root 1.253 const_iv (HOOK_OSC_SEQ),
834     const_iv (HOOK_OSC_SEQ_PERL),
835 root 1.218
836 root 1.123 const_iv (NUM_RESOURCES),
837 root 1.62 const_iv (DEFAULT_RSTYLE),
838     const_iv (OVERLAY_RSTYLE),
839 root 1.131 const_iv (Color_Bits),
840     const_iv (RS_bgShift), const_iv (RS_bgMask),
841     const_iv (RS_fgShift), const_iv (RS_fgMask),
842     const_iv (RS_Careful),
843     const_iv (RS_fontCount),
844     const_iv (RS_fontShift),
845     const_iv (RS_fontMask),
846     const_iv (RS_baseattrMask),
847     const_iv (RS_attrMask),
848     const_iv (RS_redraw),
849     const_iv (RS_Sel),
850 root 1.62 const_iv (RS_Bold),
851     const_iv (RS_Italic),
852     const_iv (RS_Blink),
853     const_iv (RS_RVid),
854     const_iv (RS_Uline),
855    
856 root 1.216 // TODO: should support all colour constants, create colorinc.h &c
857     const_iv (Color_fg),
858     const_iv (Color_bg),
859 root 1.257 # if OFF_FOCUS_FADING
860 root 1.216 const_iv (Color_fade),
861 root 1.257 # endif
862 root 1.216 const_iv (Color_pointer_fg),
863     const_iv (Color_pointer_bg),
864     const_iv (Color_border),
865     const_iv (NRS_COLORS),
866     const_iv (TOTAL_COLORS),
867    
868 root 1.258 const_iv (None),
869 root 1.62 const_iv (CurrentTime),
870     const_iv (ShiftMask),
871     const_iv (LockMask),
872     const_iv (ControlMask),
873     const_iv (Mod1Mask),
874     const_iv (Mod2Mask),
875     const_iv (Mod3Mask),
876     const_iv (Mod4Mask),
877     const_iv (Mod5Mask),
878     const_iv (Button1Mask),
879     const_iv (Button2Mask),
880     const_iv (Button3Mask),
881     const_iv (Button4Mask),
882     const_iv (Button5Mask),
883     const_iv (AnyModifier),
884    
885 root 1.102 const_iv (NoSymbol),
886     const_iv (GrabModeSync),
887     const_iv (GrabModeAsync),
888    
889 root 1.62 const_iv (NoEventMask),
890     const_iv (KeyPressMask),
891     const_iv (KeyReleaseMask),
892     const_iv (ButtonPressMask),
893     const_iv (ButtonReleaseMask),
894     const_iv (EnterWindowMask),
895     const_iv (LeaveWindowMask),
896     const_iv (PointerMotionMask),
897     const_iv (PointerMotionHintMask),
898     const_iv (Button1MotionMask),
899     const_iv (Button2MotionMask),
900     const_iv (Button3MotionMask),
901     const_iv (Button4MotionMask),
902     const_iv (Button5MotionMask),
903     const_iv (ButtonMotionMask),
904     const_iv (KeymapStateMask),
905     const_iv (ExposureMask),
906     const_iv (VisibilityChangeMask),
907     const_iv (StructureNotifyMask),
908     const_iv (ResizeRedirectMask),
909     const_iv (SubstructureNotifyMask),
910     const_iv (SubstructureRedirectMask),
911     const_iv (FocusChangeMask),
912     const_iv (PropertyChangeMask),
913     const_iv (ColormapChangeMask),
914     const_iv (OwnerGrabButtonMask),
915    
916     const_iv (KeyPress),
917     const_iv (KeyRelease),
918     const_iv (ButtonPress),
919     const_iv (ButtonRelease),
920     const_iv (MotionNotify),
921     const_iv (EnterNotify),
922     const_iv (LeaveNotify),
923     const_iv (FocusIn),
924     const_iv (FocusOut),
925     const_iv (KeymapNotify),
926     const_iv (Expose),
927     const_iv (GraphicsExpose),
928     const_iv (NoExpose),
929     const_iv (VisibilityNotify),
930     const_iv (CreateNotify),
931     const_iv (DestroyNotify),
932     const_iv (UnmapNotify),
933     const_iv (MapNotify),
934     const_iv (MapRequest),
935     const_iv (ReparentNotify),
936     const_iv (ConfigureNotify),
937     const_iv (ConfigureRequest),
938     const_iv (GravityNotify),
939     const_iv (ResizeRequest),
940     const_iv (CirculateNotify),
941     const_iv (CirculateRequest),
942     const_iv (PropertyNotify),
943     const_iv (SelectionClear),
944     const_iv (SelectionRequest),
945     const_iv (SelectionNotify),
946     const_iv (ColormapNotify),
947     const_iv (ClientMessage),
948     const_iv (MappingNotify),
949 root 1.257
950     // shape extension
951     const_iv (ShapeSet),
952     const_iv (ShapeUnion),
953     const_iv (ShapeIntersect),
954     const_iv (ShapeSubtract),
955     const_iv (ShapeInvert),
956    
957     const_iv (ShapeBounding),
958     const_iv (ShapeClip),
959     const_iv (ShapeInput),
960    
961     // XIM
962 root 1.91 # if ENABLE_XIM_ONTHESPOT
963     const_iv (XIMReverse),
964     const_iv (XIMUnderline),
965     const_iv (XIMHighlight),
966     const_iv (XIMPrimary),
967     const_iv (XIMSecondary),
968     const_iv (XIMTertiary),
969     const_iv (XIMVisibleToForward),
970     const_iv (XIMVisibleToBackword),
971     const_iv (XIMVisibleToCenter),
972 root 1.257 # endif
973     # if XRENDER
974 root 1.158 const_iv (PictStandardARGB32),
975     const_iv (PictStandardRGB24),
976     const_iv (PictStandardA8),
977     const_iv (PictStandardA4),
978     const_iv (PictStandardA1),
979 root 1.159 const_iv (RepeatNone),
980     const_iv (RepeatNormal),
981     const_iv (RepeatPad),
982     const_iv (RepeatReflect),
983 root 1.198 // all versions
984     const_iv (PictOpClear),
985     const_iv (PictOpSrc),
986     const_iv (PictOpDst),
987     const_iv (PictOpOver),
988     const_iv (PictOpOverReverse),
989     const_iv (PictOpIn),
990     const_iv (PictOpInReverse),
991     const_iv (PictOpOut),
992     const_iv (PictOpOutReverse),
993     const_iv (PictOpAtop),
994     const_iv (PictOpAtopReverse),
995     const_iv (PictOpXor),
996     const_iv (PictOpAdd),
997     const_iv (PictOpSaturate),
998     // 0.2+
999     const_iv (PictOpDisjointClear),
1000     const_iv (PictOpDisjointSrc),
1001     const_iv (PictOpDisjointDst),
1002     const_iv (PictOpDisjointOver),
1003     const_iv (PictOpDisjointOverReverse),
1004     const_iv (PictOpDisjointIn),
1005     const_iv (PictOpDisjointInReverse),
1006     const_iv (PictOpDisjointOut),
1007     const_iv (PictOpDisjointOutReverse),
1008     const_iv (PictOpDisjointAtop),
1009     const_iv (PictOpDisjointAtopReverse),
1010     const_iv (PictOpDisjointXor),
1011     const_iv (PictOpConjointClear),
1012     const_iv (PictOpConjointSrc),
1013     const_iv (PictOpConjointDst),
1014     const_iv (PictOpConjointOver),
1015     const_iv (PictOpConjointOverReverse),
1016     const_iv (PictOpConjointIn),
1017     const_iv (PictOpConjointInReverse),
1018     const_iv (PictOpConjointOut),
1019     const_iv (PictOpConjointOutReverse),
1020     const_iv (PictOpConjointAtop),
1021     const_iv (PictOpConjointAtopReverse),
1022     const_iv (PictOpConjointXor),
1023     // 0.11+
1024     const_iv (PictOpMultiply),
1025     const_iv (PictOpScreen),
1026     const_iv (PictOpOverlay),
1027     const_iv (PictOpDarken),
1028     const_iv (PictOpLighten),
1029     const_iv (PictOpColorDodge),
1030     const_iv (PictOpColorBurn),
1031     const_iv (PictOpHardLight),
1032     const_iv (PictOpSoftLight),
1033     const_iv (PictOpDifference),
1034     const_iv (PictOpExclusion),
1035     const_iv (PictOpHSLHue),
1036     const_iv (PictOpHSLSaturation),
1037     const_iv (PictOpHSLColor),
1038     const_iv (PictOpHSLLuminosity),
1039 root 1.257 # endif
1040 root 1.92 # if 0
1041 root 1.91 const_iv (XIMForwardChar),
1042     const_iv (XIMBackwardChar),
1043     const_iv (XIMForwardWord),
1044     const_iv (XIMBackwardWord),
1045     const_iv (XIMCaretUp),
1046     const_iv (XIMCaretDown),
1047     const_iv (XIMNextLine),
1048     const_iv (XIMPreviousLine),
1049     const_iv (XIMLineStart),
1050     const_iv (XIMLineEnd),
1051     const_iv (XIMAbsolutePosition),
1052     const_iv (XIMDontChange),
1053     # endif
1054 root 1.241
1055     /* DEC private modes */
1056     const_iv (PrivMode_132),
1057     const_iv (PrivMode_132OK),
1058     const_iv (PrivMode_rVideo),
1059     const_iv (PrivMode_relOrigin),
1060     const_iv (PrivMode_Screen),
1061     const_iv (PrivMode_Autowrap),
1062     const_iv (PrivMode_aplCUR),
1063     const_iv (PrivMode_aplKP),
1064     const_iv (PrivMode_HaveBackSpace),
1065     const_iv (PrivMode_BackSpace),
1066     const_iv (PrivMode_ShiftKeys),
1067     const_iv (PrivMode_VisibleCursor),
1068     const_iv (PrivMode_MouseX10),
1069     const_iv (PrivMode_MouseX11),
1070     const_iv (PrivMode_scrollBar),
1071     const_iv (PrivMode_TtyOutputInh),
1072     const_iv (PrivMode_Keypress),
1073     const_iv (PrivMode_smoothScroll),
1074     const_iv (PrivMode_vt52),
1075     const_iv (PrivMode_LFNL),
1076     const_iv (PrivMode_MouseBtnEvent),
1077     const_iv (PrivMode_MouseAnyEvent),
1078     const_iv (PrivMode_BracketPaste),
1079 sf-exg 1.248 const_iv (PrivMode_ExtMouseUTF8),
1080     const_iv (PrivMode_ExtMouseUrxvt),
1081 root 1.241 const_iv (PrivMode_BlinkingCursor),
1082     const_iv (PrivMode_mouse_report),
1083     const_iv (PrivMode_Default),
1084 root 1.62 };
1085    
1086 root 1.143 for (civ = const_iv + ecb_array_length (const_iv); civ > const_iv; civ--)
1087     newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
1088 root 1.1 }
1089    
1090     void
1091 root 1.232 log (utf8_string msg)
1092 root 1.171 CODE:
1093     rxvt_log ("%s", msg);
1094    
1095     void
1096 root 1.232 warn (utf8_string msg)
1097 root 1.1 CODE:
1098     rxvt_warn ("%s", msg);
1099    
1100     void
1101 root 1.232 fatal (utf8_string msg)
1102 root 1.1 CODE:
1103     rxvt_fatal ("%s", msg);
1104    
1105 root 1.59 void
1106     _exit (int status)
1107    
1108 root 1.167 void
1109     catch_fatal (SV *block)
1110     PROTOTYPE: &
1111     CODE:
1112     try
1113     {
1114     PUSHMARK (SP);
1115     PUTBACK;
1116     call_sv (block, G_VOID | G_DISCARD);
1117     SPAGAIN;
1118     }
1119     catch (const rxvt_failure_exception &e)
1120     {
1121     croak ("rxvt_fatal exception caught, trying to continue.");
1122     }
1123    
1124 root 1.3 NV
1125     NOW ()
1126     CODE:
1127 root 1.116 RETVAL = ev::now ();
1128 root 1.3 OUTPUT:
1129     RETVAL
1130    
1131 root 1.11 int
1132     GET_BASEFG (int rend)
1133     CODE:
1134     RETVAL = GET_BASEFG (rend);
1135     OUTPUT:
1136     RETVAL
1137    
1138     int
1139     GET_BASEBG (int rend)
1140     CODE:
1141     RETVAL = GET_BASEBG (rend);
1142     OUTPUT:
1143     RETVAL
1144    
1145     int
1146 root 1.12 SET_FGCOLOR (int rend, int new_color)
1147 root 1.11 CODE:
1148 root 1.98 RETVAL = SET_FGCOLOR (rend, clamp (new_color, 0, TOTAL_COLORS - 1));
1149 root 1.11 OUTPUT:
1150     RETVAL
1151    
1152     int
1153 root 1.12 SET_BGCOLOR (int rend, int new_color)
1154 root 1.11 CODE:
1155 root 1.98 RETVAL = SET_BGCOLOR (rend, clamp (new_color, 0, TOTAL_COLORS - 1));
1156 root 1.12 OUTPUT:
1157     RETVAL
1158    
1159     int
1160     GET_CUSTOM (int rend)
1161     CODE:
1162 root 1.108 RETVAL = (rend & RS_customMask) >> RS_customShift;
1163 root 1.12 OUTPUT:
1164     RETVAL
1165    
1166     int
1167     SET_CUSTOM (int rend, int new_value)
1168     CODE:
1169     {
1170     if (!IN_RANGE_EXC (new_value, 0, RS_customCount))
1171 sf-exg 1.256 croak ("custom value out of range, must be 0..%lu", RS_customCount - 1);
1172 root 1.12
1173     RETVAL = (rend & ~RS_customMask)
1174     | ((new_value << RS_customShift) & RS_customMask);
1175     }
1176 root 1.11 OUTPUT:
1177     RETVAL
1178    
1179 root 1.95 void
1180     termlist ()
1181     PPCODE:
1182     {
1183     EXTEND (SP, rxvt_term::termlist.size ());
1184    
1185     for (rxvt_term **t = rxvt_term::termlist.begin (); t < rxvt_term::termlist.end (); t++)
1186     if ((*t)->perl.self)
1187     PUSHs (sv_2mortal (newSVterm (*t)));
1188     }
1189    
1190 root 1.139 IV
1191     _new_selection_request (rxvt_term *term, int selnum, Time tm, Window win, Atom prop, SV *cb)
1192     CODE:
1193     rxvt_selection *req = new rxvt_selection (term->display, selnum, tm, win, prop, term);
1194     req->cb_sv = newSVsv (cb);
1195 sf-exg 1.142 AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_selection", 10, 0));
1196     av_push (av, newSViv ((IV)req));
1197 root 1.139 RETVAL = (IV)req;
1198     OUTPUT:
1199     RETVAL
1200    
1201     void
1202     _delete_selection_request (IV req_)
1203     CODE:
1204     rxvt_selection *req = (rxvt_selection *)req_;
1205 sf-exg 1.142 AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)req->term->perl.self), "_selection", 10, 0));
1206     int i;
1207    
1208     for (i = AvFILL (av); i >= 0; i--)
1209     if (SvIV (*av_fetch (av, i, 1)) == req_)
1210     break;
1211    
1212     for (; i < AvFILL (av); i++)
1213     av_store (av, i, SvREFCNT_inc (*av_fetch (av, i + 1, 0)));
1214    
1215     av_pop (av);
1216    
1217 root 1.139 delete req;
1218    
1219 root 1.258 Region
1220     XCreateRegion ()
1221    
1222     int
1223     XUnionRectWithRegion (int x, int y, int w, int h, Region src, Region dst)
1224     CODE:
1225     XRectangle rect;
1226     rect.x = x;
1227     rect.y = y;
1228     rect.width = w;
1229     rect.height = h;
1230     RETVAL = XUnionRectWithRegion (&rect, src, dst);
1231     OUTPUT: RETVAL
1232    
1233     int
1234     XIntersectRegion (Region src1, Region src2, Region res)
1235    
1236     int
1237     XUnionRegion (Region src1, Region src2, Region res)
1238    
1239     int
1240     XSubtractRegion (Region src1, Region src2, Region res)
1241    
1242     int
1243     XXorRegion (Region src1, Region src2, Region res)
1244    
1245     int
1246     XOffsetRegion (Region r, int dx, int dy)
1247    
1248     int
1249     XShrinkRegion (Region r, int dx, int dy)
1250    
1251     int
1252     XDestroyRegion (Region r)
1253    
1254 root 1.3 MODULE = urxvt PACKAGE = urxvt::term
1255    
1256 root 1.54 SV *
1257 root 1.95 _new (AV *env, AV *arg)
1258 root 1.54 CODE:
1259     {
1260     rxvt_term *term = new rxvt_term;
1261    
1262 root 1.88 stringvec *argv = new stringvec;
1263 root 1.95 for (int i = 0; i <= AvFILL (arg); i++)
1264     argv->push_back (strdup (SvPVbyte_nolen (*av_fetch (arg, i, 1))));
1265 root 1.54
1266 root 1.148 stringvec *envv = new stringvec;
1267 root 1.88 for (int i = AvFILL (env) + 1; i--; )
1268     envv->push_back (strdup (SvPVbyte_nolen (*av_fetch (env, i, 1))));
1269 root 1.54
1270     try
1271     {
1272 root 1.117 term->init (argv, envv);
1273 root 1.54 }
1274     catch (const class rxvt_failure_exception &e)
1275     {
1276     term->destroy ();
1277     croak ("error while initializing new terminal instance");
1278     }
1279    
1280     RETVAL = term && term->perl.self
1281     ? newSVterm (term) : &PL_sv_undef;
1282     }
1283     OUTPUT:
1284     RETVAL
1285    
1286 root 1.28 void
1287     rxvt_term::destroy ()
1288    
1289 root 1.35 void
1290 root 1.62 rxvt_term::set_should_invoke (int htype, int inc)
1291     CODE:
1292 root 1.166 uint8_t &count = THIS->perl.should_invoke [htype];
1293     uint8_t prev = count;
1294     count += inc;
1295     if (!prev != !count)
1296     {
1297     // hook status changed, react
1298     switch (htype)
1299     {
1300     case HOOK_POSITION_CHANGE:
1301     if (count)
1302     THIS->get_window_origin (THIS->parent_x, THIS->parent_y);
1303     }
1304     }
1305 root 1.62
1306 root 1.173 void
1307     rxvt_term::put_option_db (octet_string specifier, octet_string value)
1308     CODE:
1309     XrmPutStringResource (&THIS->option_db, specifier, value);
1310    
1311 root 1.223 void
1312     rxvt_term::_keysym_resources ()
1313     PPCODE:
1314     PUTBACK;
1315     _keysym_resources (THIS);
1316     SPAGAIN;
1317    
1318 root 1.102 int
1319 root 1.95 rxvt_term::grab_button (int button, U32 modifiers, Window window = THIS->vt)
1320 root 1.36 CODE:
1321 root 1.102 RETVAL = XGrabButton (THIS->dpy, button, modifiers, window, 1,
1322     ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
1323     GrabModeSync, GrabModeSync, None, GRAB_CURSOR);
1324     OUTPUT: RETVAL
1325 root 1.36
1326 root 1.102 int
1327 root 1.95 rxvt_term::ungrab_button (int button, U32 modifiers, Window window = THIS->vt)
1328     CODE:
1329 root 1.102 RETVAL = XUngrabButton (THIS->dpy, button, modifiers, window);
1330     OUTPUT: RETVAL
1331 root 1.95
1332 root 1.102 void
1333     rxvt_term::XGrabKey (int keycode, U32 modifiers, Window window = THIS->vt, \
1334     int owner_events = 1, int pointer_mode = GrabModeAsync, int keyboard_mode = GrabModeAsync)
1335     CODE:
1336     XGrabKey (THIS->dpy, keycode, modifiers, window, owner_events, pointer_mode, keyboard_mode);
1337 root 1.95
1338     void
1339 root 1.102 rxvt_term::XUngrabKey (int keycode, U32 modifiers, Window window = THIS->vt)
1340     CODE:
1341     XUngrabKey (THIS->dpy, keycode, modifiers, window);
1342 root 1.95
1343 root 1.36 bool
1344 root 1.79 rxvt_term::grab (Time eventtime, int sync = 0)
1345 root 1.35 CODE:
1346     {
1347 root 1.36 int mode = sync ? GrabModeSync : GrabModeAsync;
1348    
1349     THIS->perl.grabtime = 0;
1350    
1351 root 1.96 if (!XGrabPointer (THIS->dpy, THIS->vt, 0,
1352 root 1.36 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
1353 root 1.41 mode, mode, None, GRAB_CURSOR, eventtime))
1354 root 1.96 if (!XGrabKeyboard (THIS->dpy, THIS->vt, 0, mode, mode, eventtime))
1355 root 1.36 THIS->perl.grabtime = eventtime;
1356     else
1357 root 1.96 XUngrabPointer (THIS->dpy, eventtime);
1358 root 1.36
1359     RETVAL = !!THIS->perl.grabtime;
1360 root 1.35 }
1361 root 1.36 OUTPUT:
1362     RETVAL
1363    
1364     void
1365 root 1.44 rxvt_term::allow_events_async ()
1366 root 1.36 CODE:
1367 root 1.96 XAllowEvents (THIS->dpy, AsyncBoth, THIS->perl.grabtime);
1368 root 1.36
1369     void
1370 root 1.44 rxvt_term::allow_events_sync ()
1371 root 1.36 CODE:
1372 root 1.96 XAllowEvents (THIS->dpy, SyncBoth, THIS->perl.grabtime);
1373 root 1.36
1374     void
1375 root 1.44 rxvt_term::allow_events_replay ()
1376 root 1.36 CODE:
1377 root 1.96 XAllowEvents (THIS->dpy, ReplayPointer, THIS->perl.grabtime);
1378     XAllowEvents (THIS->dpy, ReplayKeyboard, THIS->perl.grabtime);
1379 root 1.36
1380     void
1381 root 1.44 rxvt_term::ungrab ()
1382 root 1.36 CODE:
1383 root 1.45 ungrab (THIS);
1384 root 1.35
1385 root 1.1 int
1386 root 1.232 rxvt_term::XStringToKeysym (octet_string string)
1387 root 1.102 CODE:
1388     RETVAL = XStringToKeysym (string);
1389     OUTPUT: RETVAL
1390    
1391     char *
1392     rxvt_term::XKeysymToString (int sym)
1393     CODE:
1394     RETVAL = XKeysymToString (sym);
1395     OUTPUT: RETVAL
1396    
1397     int
1398     rxvt_term::XKeysymToKeycode (int sym)
1399     CODE:
1400     RETVAL = XKeysymToKeycode (THIS->dpy, sym);
1401     OUTPUT: RETVAL
1402    
1403     int
1404     rxvt_term::XKeycodeToKeysym (int code, int index)
1405     CODE:
1406 sf-exg 1.228 RETVAL = rxvt_XKeycodeToKeysym (THIS->dpy, code, index);
1407 root 1.102 OUTPUT: RETVAL
1408    
1409     int
1410 root 1.3 rxvt_term::strwidth (SV *str)
1411 root 1.1 CODE:
1412     {
1413     wchar_t *wstr = sv2wcs (str);
1414 root 1.3
1415     rxvt_push_locale (THIS->locale);
1416 root 1.105 RETVAL = 0;
1417     for (wchar_t *wc = wstr; *wc; wc++)
1418     {
1419     int w = WCWIDTH (*wc);
1420    
1421     if (w)
1422 root 1.107 RETVAL += max (w, 1);
1423 root 1.105 }
1424 root 1.3 rxvt_pop_locale ();
1425    
1426 root 1.1 free (wstr);
1427     }
1428     OUTPUT:
1429     RETVAL
1430    
1431 root 1.3 SV *
1432     rxvt_term::locale_encode (SV *str)
1433 root 1.1 CODE:
1434 root 1.3 {
1435 root 1.254 if (!SvOK (str))
1436     XSRETURN_UNDEF;
1437    
1438 root 1.3 wchar_t *wstr = sv2wcs (str);
1439    
1440     rxvt_push_locale (THIS->locale);
1441     char *mbstr = rxvt_wcstombs (wstr);
1442     rxvt_pop_locale ();
1443    
1444     free (wstr);
1445    
1446 root 1.71 RETVAL = newSVpv (mbstr, 0);
1447 root 1.3 free (mbstr);
1448     }
1449     OUTPUT:
1450 root 1.1 RETVAL
1451    
1452 root 1.3 SV *
1453     rxvt_term::locale_decode (SV *octets)
1454     CODE:
1455     {
1456 root 1.254 if (!SvOK (octets))
1457     XSRETURN_UNDEF;
1458    
1459 root 1.3 STRLEN len;
1460     char *data = SvPVbyte (octets, len);
1461    
1462     rxvt_push_locale (THIS->locale);
1463     wchar_t *wstr = rxvt_mbstowcs (data, len);
1464     rxvt_pop_locale ();
1465    
1466 root 1.71 RETVAL = wcs2sv (wstr);
1467 root 1.3 free (wstr);
1468     }
1469     OUTPUT:
1470     RETVAL
1471 root 1.1
1472 root 1.38 #define TERM_OFFSET(sym) offsetof (TermWin_t, sym)
1473 root 1.24
1474 root 1.127 #define TERM_OFFSET_width TERM_OFFSET(width)
1475     #define TERM_OFFSET_height TERM_OFFSET(height)
1476     #define TERM_OFFSET_fwidth TERM_OFFSET(fwidth)
1477     #define TERM_OFFSET_fheight TERM_OFFSET(fheight)
1478     #define TERM_OFFSET_fbase TERM_OFFSET(fbase)
1479     #define TERM_OFFSET_nrow TERM_OFFSET(nrow)
1480     #define TERM_OFFSET_ncol TERM_OFFSET(ncol)
1481     #define TERM_OFFSET_focus TERM_OFFSET(focus)
1482     #define TERM_OFFSET_mapped TERM_OFFSET(mapped)
1483     #define TERM_OFFSET_int_bwidth TERM_OFFSET(int_bwidth)
1484     #define TERM_OFFSET_ext_bwidth TERM_OFFSET(ext_bwidth)
1485     #define TERM_OFFSET_lineSpace TERM_OFFSET(lineSpace)
1486     #define TERM_OFFSET_letterSpace TERM_OFFSET(letterSpace)
1487     #define TERM_OFFSET_saveLines TERM_OFFSET(saveLines)
1488     #define TERM_OFFSET_total_rows TERM_OFFSET(total_rows)
1489     #define TERM_OFFSET_top_row TERM_OFFSET(top_row)
1490 root 1.24
1491     int
1492 root 1.237 rxvt_term::width (int new_value = NO_INIT)
1493 root 1.24 ALIAS:
1494 root 1.127 width = TERM_OFFSET_width
1495     height = TERM_OFFSET_height
1496     fwidth = TERM_OFFSET_fwidth
1497     fheight = TERM_OFFSET_fheight
1498     fbase = TERM_OFFSET_fbase
1499     nrow = TERM_OFFSET_nrow
1500     ncol = TERM_OFFSET_ncol
1501     focus = TERM_OFFSET_focus
1502     mapped = TERM_OFFSET_mapped
1503     int_bwidth = TERM_OFFSET_int_bwidth
1504     ext_bwidth = TERM_OFFSET_ext_bwidth
1505     lineSpace = TERM_OFFSET_lineSpace
1506     letterSpace = TERM_OFFSET_letterSpace
1507     saveLines = TERM_OFFSET_saveLines
1508     total_rows = TERM_OFFSET_total_rows
1509     top_row = TERM_OFFSET_top_row
1510 root 1.24 CODE:
1511     RETVAL = *(int *)((char *)THIS + ix);
1512 root 1.237 if (items > 1)
1513     *(int *)((char *)THIS + ix) = new_value;
1514 root 1.24 OUTPUT:
1515     RETVAL
1516    
1517 root 1.38 unsigned int
1518     rxvt_term::ModLevel3Mask ()
1519     ALIAS:
1520     ModLevel3Mask = 0
1521     ModMetaMask = 1
1522     ModNumLockMask = 2
1523 root 1.86 current_screen = 3
1524 root 1.87 hidden_cursor = 4
1525 root 1.241 priv_modes = 5
1526 root 1.38 CODE:
1527     switch (ix)
1528     {
1529 root 1.87 case 0: RETVAL = THIS->ModLevel3Mask; break;
1530     case 1: RETVAL = THIS->ModMetaMask; break;
1531     case 2: RETVAL = THIS->ModNumLockMask; break;
1532     case 3: RETVAL = THIS->current_screen; break;
1533 root 1.124 #ifdef CURSOR_BLINK
1534 root 1.87 case 4: RETVAL = THIS->hidden_cursor; break;
1535 root 1.240 #else
1536     case 4: RETVAL = 0; break;
1537 root 1.124 #endif
1538 root 1.241 case 5: RETVAL = THIS->priv_modes; break;
1539 root 1.38 }
1540     OUTPUT:
1541     RETVAL
1542    
1543 root 1.48 char *
1544     rxvt_term::display_id ()
1545 root 1.49 ALIAS:
1546     display_id = 0
1547     locale = 1
1548 root 1.48 CODE:
1549 root 1.49 switch (ix)
1550     {
1551     case 0: RETVAL = THIS->display->id; break;
1552     case 1: RETVAL = THIS->locale; break;
1553     }
1554 root 1.48 OUTPUT:
1555     RETVAL
1556    
1557 root 1.54 SV *
1558 root 1.100 rxvt_term::envv ()
1559     ALIAS:
1560     argv = 1
1561     PPCODE:
1562 root 1.54 {
1563 root 1.100 stringvec *vec = ix ? THIS->argv : THIS->envv;
1564 root 1.54
1565 root 1.100 EXTEND (SP, vec->size ());
1566 root 1.54
1567 root 1.100 for (char **i = vec->begin (); i != vec->end (); ++i)
1568     if (*i)
1569     PUSHs (sv_2mortal (newSVpv (*i, 0)));
1570 root 1.54 }
1571    
1572 root 1.50 int
1573 root 1.116 rxvt_term::pty_ev_events (int events = ev::UNDEF)
1574 root 1.50 CODE:
1575     RETVAL = THIS->pty_ev.events;
1576 root 1.116 if (events != ev::UNDEF)
1577 root 1.50 THIS->pty_ev.set (events);
1578     OUTPUT:
1579     RETVAL
1580    
1581 root 1.90 int
1582     rxvt_term::pty_fd ()
1583     CODE:
1584     RETVAL = THIS->pty->pty;
1585     OUTPUT:
1586     RETVAL
1587    
1588 root 1.79 Window
1589 root 1.31 rxvt_term::parent ()
1590     CODE:
1591 sf-exg 1.140 RETVAL = THIS->parent;
1592 root 1.31 OUTPUT:
1593     RETVAL
1594    
1595 root 1.166 int
1596     rxvt_term::parent_x ()
1597     CODE:
1598     RETVAL = THIS->parent_x;
1599     OUTPUT:
1600     RETVAL
1601    
1602     int
1603     rxvt_term::parent_y ()
1604 root 1.30 CODE:
1605 root 1.166 RETVAL = THIS->parent_y;
1606 root 1.30 OUTPUT:
1607     RETVAL
1608    
1609 sf-exg 1.202 Window
1610     rxvt_term::vt ()
1611     CODE:
1612     RETVAL = THIS->vt;
1613     OUTPUT:
1614     RETVAL
1615    
1616 root 1.62 void
1617     rxvt_term::vt_emask_add (U32 emask)
1618     CODE:
1619     THIS->vt_emask_perl |= emask;
1620     THIS->vt_select_input ();
1621    
1622 root 1.30 U32
1623 root 1.25 rxvt_term::rstyle (U32 new_rstyle = THIS->rstyle)
1624 root 1.7 CODE:
1625 root 1.25 RETVAL = THIS->rstyle;
1626     THIS->rstyle = new_rstyle;
1627 root 1.7 OUTPUT:
1628 root 1.24 RETVAL
1629 root 1.7
1630     int
1631 root 1.252 rxvt_term::view_start (int newval = 0)
1632 root 1.61 PROTOTYPE: $;$
1633 root 1.7 CODE:
1634     {
1635     RETVAL = THIS->view_start;
1636 sf-exg 1.251 if (items > 1)
1637     THIS->scr_changeview (newval);
1638 root 1.7 }
1639     OUTPUT:
1640     RETVAL
1641    
1642 root 1.8 void
1643 sf-exg 1.146 rxvt_term::set_urgency (bool enable)
1644    
1645     void
1646 root 1.83 rxvt_term::focus_in ()
1647    
1648     void
1649     rxvt_term::focus_out ()
1650    
1651     void
1652 root 1.98 rxvt_term::key_press (unsigned int state, unsigned int keycode, Time time = CurrentTime)
1653     ALIAS:
1654     key_release = 1
1655     CODE:
1656     {
1657     XKeyEvent xkey;
1658    
1659     memset (&xkey, 0, sizeof (xkey));
1660    
1661     xkey.time = time;
1662     xkey.state = state;
1663     xkey.keycode = keycode;
1664    
1665     xkey.type = ix ? KeyRelease : KeyPress;
1666     xkey.display = THIS->dpy;
1667     xkey.window = THIS->vt;
1668     xkey.root = THIS->display->root;
1669     xkey.subwindow = THIS->vt;
1670    
1671     if (ix)
1672     THIS->key_release (xkey);
1673     else
1674     THIS->key_press (xkey);
1675     }
1676    
1677     void
1678 root 1.9 rxvt_term::want_refresh ()
1679     CODE:
1680     THIS->want_refresh = 1;
1681 root 1.118 THIS->refresh_check ();
1682 root 1.9
1683     void
1684 sf-exg 1.234 rxvt_term::refresh_check ()
1685    
1686     void
1687 root 1.27 rxvt_term::ROW_t (int row_number, SV *new_text = 0, int start_col = 0, int start_ofs = 0, int max_len = MAX_COLS)
1688 root 1.8 PPCODE:
1689     {
1690 root 1.67 if (!IN_RANGE_EXC (row_number, THIS->top_row, THIS->nrow))
1691 root 1.19 XSRETURN_EMPTY;
1692 root 1.8
1693     line_t &l = ROW(row_number);
1694    
1695     if (GIMME_V != G_VOID)
1696     {
1697 root 1.91 wchar_t *wstr = rxvt_temp_buf<wchar_t> (THIS->ncol);
1698 root 1.8
1699 root 1.33 for (int col = 0; col < THIS->ncol; col++)
1700 root 1.8 wstr [col] = l.t [col];
1701    
1702 root 1.71 XPUSHs (sv_2mortal (wcs2sv (wstr, THIS->ncol)));
1703 root 1.8 }
1704    
1705     if (new_text)
1706     {
1707 root 1.13 wchar_t *wstr = sv2wcs (new_text);
1708 root 1.8
1709 root 1.27 int len = min (wcslen (wstr) - start_ofs, max_len);
1710 root 1.8
1711 root 1.83 if (start_col < 0 || start_col + len > THIS->ncol)
1712 root 1.8 {
1713     free (wstr);
1714 root 1.10 croak ("new_text extends beyond horizontal margins");
1715 root 1.8 }
1716    
1717     for (int col = start_col; col < start_col + len; col++)
1718     {
1719 root 1.27 l.t [col] = wstr [start_ofs + col - start_col];
1720 root 1.8 l.r [col] = SET_FONT (l.r [col], THIS->fontset [GET_STYLE (l.r [col])]->find_font (l.t [col]));
1721     }
1722 root 1.9
1723     free (wstr);
1724 root 1.8 }
1725     }
1726    
1727     void
1728 root 1.27 rxvt_term::ROW_r (int row_number, SV *new_rend = 0, int start_col = 0, int start_ofs = 0, int max_len = MAX_COLS)
1729 root 1.8 PPCODE:
1730     {
1731 root 1.67 if (!IN_RANGE_EXC (row_number, THIS->top_row, THIS->nrow))
1732 root 1.19 XSRETURN_EMPTY;
1733 root 1.8
1734     line_t &l = ROW(row_number);
1735    
1736     if (GIMME_V != G_VOID)
1737     {
1738     AV *av = newAV ();
1739    
1740     av_extend (av, THIS->ncol - 1);
1741     for (int col = 0; col < THIS->ncol; col++)
1742     av_store (av, col, newSViv (l.r [col]));
1743    
1744     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
1745     }
1746    
1747     if (new_rend)
1748     {
1749     if (!SvROK (new_rend) || SvTYPE (SvRV (new_rend)) != SVt_PVAV)
1750     croak ("new_rend must be arrayref");
1751    
1752     AV *av = (AV *)SvRV (new_rend);
1753 root 1.76 int len = min (AvFILL (av) + 1 - start_ofs, max_len);
1754 root 1.8
1755 root 1.83 if (start_col < 0 || start_col + len > THIS->ncol)
1756 root 1.10 croak ("new_rend array extends beyond horizontal margins");
1757 root 1.8
1758     for (int col = start_col; col < start_col + len; col++)
1759     {
1760 root 1.27 rend_t r = SvIV (*av_fetch (av, start_ofs + col - start_col, 1)) & ~RS_fontMask;
1761 root 1.8
1762     l.r [col] = SET_FONT (r, THIS->fontset [GET_STYLE (r)]->find_font (l.t [col]));
1763     }
1764     }
1765     }
1766    
1767     int
1768 root 1.26 rxvt_term::ROW_l (int row_number, int new_length = -1)
1769 root 1.8 CODE:
1770     {
1771 root 1.67 if (!IN_RANGE_EXC (row_number, THIS->top_row, THIS->nrow))
1772 root 1.19 XSRETURN_EMPTY;
1773 root 1.8
1774     line_t &l = ROW(row_number);
1775 root 1.26 RETVAL = l.l;
1776 root 1.8
1777 root 1.26 if (new_length >= 0)
1778 root 1.8 l.l = new_length;
1779     }
1780     OUTPUT:
1781     RETVAL
1782    
1783 root 1.19 bool
1784 root 1.26 rxvt_term::ROW_is_longer (int row_number, int new_is_longer = -1)
1785 root 1.19 CODE:
1786     {
1787 root 1.67 if (!IN_RANGE_EXC (row_number, THIS->top_row, THIS->nrow))
1788 root 1.19 XSRETURN_EMPTY;
1789    
1790     line_t &l = ROW(row_number);
1791 root 1.26 RETVAL = l.is_longer ();
1792    
1793     if (new_is_longer >= 0)
1794     l.is_longer (new_is_longer);
1795 root 1.19 }
1796     OUTPUT:
1797     RETVAL
1798    
1799 root 1.8 SV *
1800 root 1.33 rxvt_term::special_encode (SV *string)
1801 root 1.8 CODE:
1802 root 1.33 {
1803     wchar_t *wstr = sv2wcs (string);
1804     int wlen = wcslen (wstr);
1805 root 1.91 wchar_t *rstr = rxvt_temp_buf<wchar_t> (wlen * 2); // cannot become longer
1806 root 1.33
1807     rxvt_push_locale (THIS->locale);
1808    
1809     wchar_t *r = rstr;
1810     for (wchar_t *s = wstr; *s; s++)
1811 root 1.91 {
1812     int w = WCWIDTH (*s);
1813    
1814     if (w == 0)
1815     {
1816     if (r == rstr)
1817     croak ("leading combining character unencodable");
1818 root 1.33
1819 root 1.91 unicode_t n = rxvt_compose (r[-1], *s);
1820     if (n == NOCHAR)
1821     n = rxvt_composite.compose (r[-1], *s);
1822    
1823     r[-1] = n;
1824     }
1825 root 1.33 #if !UNICODE_3
1826 root 1.91 else if (*s >= 0x10000)
1827     *r++ = rxvt_composite.compose (*s);
1828 root 1.33 #endif
1829 root 1.91 else
1830     *r++ = *s;
1831    
1832     // the *2 above only allows wcwidth <= 2
1833     if (w > 1)
1834     *r++ = NOCHAR;
1835     }
1836 root 1.33
1837     rxvt_pop_locale ();
1838    
1839 sf-exg 1.230 free (wstr);
1840 root 1.71 RETVAL = wcs2sv (rstr, r - rstr);
1841 root 1.33 }
1842     OUTPUT:
1843     RETVAL
1844 root 1.8
1845     SV *
1846 root 1.33 rxvt_term::special_decode (SV *text)
1847 root 1.8 CODE:
1848 root 1.33 {
1849     wchar_t *wstr = sv2wcs (text);
1850     int dlen = 0;
1851    
1852     // find length
1853     for (wchar_t *s = wstr; *s; s++)
1854     if (*s == NOCHAR)
1855     ;
1856     else if (IS_COMPOSE (*s))
1857 root 1.250 dlen += rxvt_composite.expand (*s);
1858 root 1.33 else
1859     dlen++;
1860    
1861 root 1.91 wchar_t *rstr = rxvt_temp_buf<wchar_t> (dlen);
1862 root 1.33
1863     // decode
1864     wchar_t *r = rstr;
1865     for (wchar_t *s = wstr; *s; s++)
1866     if (*s == NOCHAR)
1867     ;
1868     else if (IS_COMPOSE (*s))
1869     r += rxvt_composite.expand (*s, r);
1870     else
1871     *r++ = *s;
1872    
1873 sf-exg 1.230 free (wstr);
1874 root 1.71 RETVAL = wcs2sv (rstr, r - rstr);
1875 root 1.33 }
1876     OUTPUT:
1877     RETVAL
1878 root 1.8
1879 root 1.1 void
1880 root 1.232 rxvt_term::_resource (octet_string name, int index, SV *newval = 0)
1881 root 1.2 PPCODE:
1882     {
1883 root 1.97 static const struct resval { const char *name; int value; } *rs, rslist [] = {
1884 root 1.21 # define def(name) { # name, Rs_ ## name },
1885     # define reserve(name,count)
1886 root 1.2 # include "rsinc.h"
1887 root 1.21 # undef def
1888     # undef reserve
1889 root 1.2 };
1890    
1891 sf-exg 1.141 rs = rslist + ecb_array_length (rslist);
1892 root 1.2
1893 root 1.123 if (*name)
1894     {
1895     do {
1896     if (rs-- == rslist)
1897     croak ("no such resource '%s', requested", name);
1898     } while (strcmp (name, rs->name));
1899 root 1.2
1900 root 1.123 index += rs->value;
1901     }
1902     else
1903     {
1904     --rs;
1905 root 1.244 name = (octet_string)"";
1906 root 1.123 }
1907 root 1.2
1908     if (!IN_RANGE_EXC (index, 0, NUM_RESOURCES))
1909     croak ("requested out-of-bound resource %s+%d,", name, index - rs->value);
1910    
1911     if (GIMME_V != G_VOID)
1912 root 1.71 XPUSHs (THIS->rs [index] ? sv_2mortal (newSVpv (THIS->rs [index], 0)) : &PL_sv_undef);
1913 root 1.2
1914     if (newval)
1915     {
1916     if (SvOK (newval))
1917     {
1918     char *str = strdup (SvPVbyte_nolen (newval));
1919     THIS->rs [index] = str;
1920     THIS->allocated.push_back (str);
1921     }
1922     else
1923     THIS->rs [index] = 0;
1924     }
1925     }
1926    
1927 root 1.55 const char *
1928 root 1.232 rxvt_term::x_resource (octet_string name)
1929 root 1.55
1930 root 1.40 bool
1931 ayin 1.113 rxvt_term::option (U8 optval, int set = -1)
1932 root 1.40 CODE:
1933     {
1934 ayin 1.113 RETVAL = THIS->option (optval);
1935 root 1.40
1936     if (set >= 0)
1937     {
1938 ayin 1.113 THIS->set_option (optval, set);
1939 root 1.40
1940 sf-exg 1.150 if (THIS->init_done) // avoid doing this before START
1941 root 1.78 switch (optval)
1942     {
1943     case Opt_skipBuiltinGlyphs:
1944     THIS->set_fonts ();
1945     THIS->scr_remap_chars ();
1946     THIS->scr_touch (true);
1947     THIS->want_refresh = 1;
1948 root 1.118 THIS->refresh_check ();
1949 root 1.78 break;
1950 sf-exg 1.153 #ifdef CURSOR_BLINK
1951     case Opt_cursorBlink:
1952     THIS->cursor_blink_reset ();
1953     break;
1954     #endif
1955    
1956 root 1.78 case Opt_cursorUnderline:
1957 sf-exg 1.225 THIS->cursor_type = set ? 1 : 0;
1958 root 1.78 THIS->want_refresh = 1;
1959 root 1.118 THIS->refresh_check ();
1960 root 1.78 break;
1961 root 1.40
1962     # case Opt_scrollBar_floating:
1963     # case Opt_scrollBar_right:
1964     # THIS->resize_all_windows (THIS->width, THIS->height, 1);
1965     # break;
1966 root 1.78 }
1967 root 1.40 }
1968     }
1969     OUTPUT:
1970     RETVAL
1971    
1972 sf-exg 1.236 SV *
1973     rxvt_term::lookup_keysym (int keysym, unsigned int state)
1974     CODE:
1975     {
1976     keysym_t *key = THIS->keyboard->lookup_keysym (THIS, keysym, state);
1977     RETVAL = key ? sv_2mortal (newSVpv (key->str, 0)) : &PL_sv_undef;
1978     }
1979     OUTPUT:
1980     RETVAL
1981    
1982 root 1.50 bool
1983 root 1.233 rxvt_term::bind_action (octet_string keysym, octet_string action)
1984 sf-exg 1.219 ALIAS:
1985     parse_keysym = 1
1986 root 1.50 CODE:
1987 root 1.232 RETVAL = 0 < THIS->bind_action (keysym, action);
1988 root 1.50 THIS->keyboard->register_done ();
1989     OUTPUT:
1990     RETVAL
1991    
1992 root 1.2 void
1993 sf-exg 1.229 rxvt_term::register_command (int keysym, unsigned int state, SV *str)
1994     CODE:
1995     wchar_t *wstr = sv2wcs (str);
1996     THIS->keyboard->register_action (keysym, state, wstr);
1997     free (wstr);
1998    
1999     void
2000 root 1.46 rxvt_term::screen_cur (...)
2001 root 1.1 PROTOTYPE: $;$$
2002     ALIAS:
2003 root 1.24 screen_cur = 0
2004     selection_beg = 1
2005     selection_end = 2
2006     selection_mark = 3
2007 root 1.1 PPCODE:
2008     {
2009 root 1.24 row_col_t &rc = ix == 0 ? THIS->screen.cur
2010     : ix == 1 ? THIS->selection.beg
2011     : ix == 2 ? THIS->selection.end
2012     : THIS->selection.mark;
2013 root 1.1
2014     if (GIMME_V != G_VOID)
2015     {
2016     EXTEND (SP, 2);
2017 root 1.24 PUSHs (sv_2mortal (newSViv (rc.row)));
2018     PUSHs (sv_2mortal (newSViv (rc.col)));
2019 root 1.1 }
2020    
2021 root 1.128 if (items >= 3)
2022 root 1.1 {
2023 root 1.73 rc.row = SvIV (ST (1));
2024     rc.col = SvIV (ST (2));
2025    
2026 root 1.89 if (ix == 2)
2027 root 1.73 {
2028 root 1.89 if (rc.col == 0)
2029     {
2030     // col == 0 means end of previous line
2031     rc.row--;
2032     rc.col = THIS->ncol;
2033     }
2034     else if (IN_RANGE_EXC (rc.row, THIS->top_row, THIS->nrow)
2035     && rc.col > ROW(rc.row).l)
2036     {
2037     // col >= length means while line and add newline
2038     rc.col = THIS->ncol;
2039     }
2040 root 1.73 }
2041    
2042     clamp_it (rc.col, 0, THIS->ncol);
2043     clamp_it (rc.row, THIS->top_row, THIS->nrow - 1);
2044 root 1.1
2045     if (ix)
2046 root 1.118 {
2047 root 1.128 THIS->selection.screen = THIS->current_screen;
2048    
2049 root 1.213 THIS->selection_changed ();
2050 root 1.118 THIS->refresh_check ();
2051     }
2052 root 1.1 }
2053     }
2054    
2055 root 1.128 int
2056     rxvt_term::selection_screen (int screen = -1)
2057 root 1.53 CODE:
2058 root 1.128 RETVAL = THIS->selection.screen;
2059     if (screen >= 0)
2060     THIS->selection.screen = screen;
2061     OUTPUT:
2062 root 1.53 RETVAL
2063    
2064 root 1.93 void
2065 sf-exg 1.215 rxvt_term::selection_request (Time tm, int selnum)
2066    
2067     void
2068 sf-exg 1.129 rxvt_term::selection_clear (bool clipboard = false)
2069    
2070     void
2071 root 1.79 rxvt_term::selection_make (Time eventtime, bool rect = false)
2072 root 1.60 CODE:
2073     THIS->selection.op = SELECTION_CONT;
2074     THIS->selection.rect = rect;
2075     THIS->selection_make (eventtime);
2076    
2077 root 1.1 int
2078 sf-exg 1.129 rxvt_term::selection_grab (Time eventtime, bool clipboard = false)
2079 root 1.1
2080     void
2081 sf-exg 1.130 rxvt_term::selection (SV *newtext = 0, bool clipboard = false)
2082 root 1.1 PPCODE:
2083     {
2084 sf-exg 1.130 wchar_t * &text = clipboard ? THIS->selection.clip_text : THIS->selection.text;
2085     unsigned int &len = clipboard ? THIS->selection.clip_len : THIS->selection.len;
2086    
2087 root 1.1 if (GIMME_V != G_VOID)
2088 sf-exg 1.130 XPUSHs (text
2089     ? sv_2mortal (wcs2sv (text, len))
2090 root 1.45 : &PL_sv_undef);
2091 root 1.1
2092     if (newtext)
2093     {
2094 sf-exg 1.130 free (text);
2095 root 1.1
2096 sf-exg 1.130 text = sv2wcs (newtext);
2097     len = wcslen (text);
2098 root 1.1 }
2099     }
2100 root 1.24
2101 root 1.128 char
2102     rxvt_term::cur_charset ()
2103     CODE:
2104     RETVAL = THIS->charsets [THIS->screen.charset];
2105     OUTPUT:
2106     RETVAL
2107    
2108 root 1.1 void
2109 root 1.51 rxvt_term::scr_xor_rect (int beg_row, int beg_col, int end_row, int end_col, U32 rstyle1 = RS_RVid, U32 rstyle2 = RS_RVid | RS_Uline)
2110    
2111     void
2112     rxvt_term::scr_xor_span (int beg_row, int beg_col, int end_row, int end_col, U32 rstyle = RS_RVid)
2113    
2114     void
2115 root 1.50 rxvt_term::scr_bell ()
2116    
2117     void
2118 root 1.231 rxvt_term::scr_recolor (bool refresh = true);
2119 root 1.161
2120     void
2121 root 1.86 rxvt_term::scr_change_screen (int screen)
2122    
2123     void
2124 root 1.25 rxvt_term::scr_add_lines (SV *string)
2125     CODE:
2126     {
2127     wchar_t *wstr = sv2wcs (string);
2128 root 1.32 THIS->scr_add_lines (wstr, wcslen (wstr));
2129 root 1.25 free (wstr);
2130     }
2131    
2132     void
2133 sf-exg 1.221 rxvt_term::tt_write_user_input (SV *octets)
2134     INIT:
2135     STRLEN len;
2136     char *str = SvPVbyte (octets, len);
2137     C_ARGS:
2138     str, len
2139    
2140     void
2141 root 1.13 rxvt_term::tt_write (SV *octets)
2142     INIT:
2143     STRLEN len;
2144     char *str = SvPVbyte (octets, len);
2145     C_ARGS:
2146 root 1.23 str, len
2147 root 1.13
2148 root 1.28 void
2149 sf-exg 1.132 rxvt_term::tt_paste (SV *octets)
2150     INIT:
2151     STRLEN len;
2152     char *str = SvPVbyte (octets, len);
2153     C_ARGS:
2154     str, len
2155    
2156     void
2157 root 1.28 rxvt_term::cmd_parse (SV *octets)
2158     CODE:
2159     {
2160     STRLEN len;
2161     char *str = SvPVbyte (octets, len);
2162    
2163     char *old_cmdbuf_ptr = THIS->cmdbuf_ptr;
2164     char *old_cmdbuf_endp = THIS->cmdbuf_endp;
2165    
2166     THIS->cmdbuf_ptr = str;
2167     THIS->cmdbuf_endp = str + len;
2168    
2169 root 1.35 rxvt_push_locale (THIS->locale);
2170 root 1.28 THIS->cmd_parse ();
2171 root 1.35 rxvt_pop_locale ();
2172 root 1.28
2173     THIS->cmdbuf_ptr = old_cmdbuf_ptr;
2174     THIS->cmdbuf_endp = old_cmdbuf_endp;
2175     }
2176    
2177 root 1.13 SV *
2178     rxvt_term::overlay (int x, int y, int w, int h, int rstyle = OVERLAY_RSTYLE, int border = 2)
2179     CODE:
2180     {
2181     overlay *o = new overlay (THIS, x, y, w, h, rstyle, border);
2182     RETVAL = newSVptr ((void *)o, "urxvt::overlay");
2183     o->self = (HV *)SvRV (RETVAL);
2184     }
2185     OUTPUT:
2186     RETVAL
2187    
2188 root 1.79 #############################################################################
2189     # Various X Utility Functions
2190     #############################################################################
2191    
2192     void
2193     rxvt_term::XListProperties (Window window)
2194     PPCODE:
2195     {
2196     int count;
2197 root 1.96 Atom *props = XListProperties (THIS->dpy, window, &count);
2198 root 1.79
2199     EXTEND (SP, count);
2200     while (count--)
2201 sf-exg 1.259 PUSHs (sv_2mortal (newSVuv ((U32)props [count])));
2202 ayin 1.115
2203 root 1.79 XFree (props);
2204     }
2205    
2206     void
2207     rxvt_term::XGetWindowProperty (Window window, Atom property)
2208     PPCODE:
2209     {
2210     Atom type;
2211     int format;
2212     unsigned long nitems;
2213     unsigned long bytes_after;
2214     unsigned char *prop;
2215 root 1.81
2216 root 1.96 XGetWindowProperty (THIS->dpy, window, property,
2217 root 1.81 0, 1<<24, 0, AnyPropertyType,
2218 root 1.79 &type, &format, &nitems, &bytes_after, &prop);
2219 root 1.81
2220 root 1.79 if (type != None)
2221     {
2222 root 1.81 int elemsize = format == 16 ? sizeof (short)
2223     : format == 32 ? sizeof (long)
2224     : 1;
2225    
2226 root 1.79 EXTEND (SP, 3);
2227 sf-exg 1.259 PUSHs (sv_2mortal (newSVuv ((U32)type)));
2228     PUSHs (sv_2mortal (newSViv (format)));
2229     PUSHs (sv_2mortal (newSVpvn ((char *)prop, nitems * elemsize)));
2230 root 1.79 XFree (prop);
2231     }
2232     }
2233    
2234     void
2235 root 1.122 rxvt_term::XChangeProperty (Window window, Atom property, Atom type, int format, SV *data)
2236 root 1.79 CODE:
2237     {
2238     STRLEN len;
2239     char *data_ = SvPVbyte (data, len);
2240    
2241 root 1.81 int elemsize = format == 16 ? sizeof (short)
2242     : format == 32 ? sizeof (long)
2243     : 1;
2244    
2245 root 1.96 XChangeProperty (THIS->dpy, window, property,
2246 root 1.79 type, format, PropModeReplace,
2247 root 1.81 (unsigned char *)data_, len / elemsize);
2248 root 1.79 }
2249    
2250 root 1.81 Atom
2251 root 1.159 XInternAtom (rxvt_term *term, octet_string atom_name, int only_if_exists = FALSE)
2252 root 1.96 C_ARGS: term->dpy, atom_name, only_if_exists
2253 root 1.81
2254     char *
2255     XGetAtomName (rxvt_term *term, Atom atom)
2256 root 1.96 C_ARGS: term->dpy, atom
2257 root 1.81 CLEANUP:
2258     XFree (RETVAL);
2259    
2260 root 1.79 void
2261     XDeleteProperty (rxvt_term *term, Window window, Atom property)
2262 root 1.159 C_ARGS: term->dpy, window, property
2263 root 1.79
2264 root 1.257 void
2265     rxvt_term::XShapeQueryVersion ()
2266     PPCODE:
2267     int major, minor;
2268     EXTEND (SP, 2);
2269     if (XShapeQueryVersion (THIS->display->dpy, &major, &minor))
2270     {
2271     PUSHs (sv_2mortal (newSViv (major)));
2272     PUSHs (sv_2mortal (newSViv (minor)));
2273     }
2274    
2275     void
2276     XShapeCombineRegion (rxvt_term *term, Window dest, int destKind, int xOff, int yOff, Region r, int op)
2277     C_ARGS: term->display->dpy, dest, destKind, xOff, yOff, r, op
2278    
2279     void
2280     XShapeCombineMask (rxvt_term *term, XID dest, int destKind, int xOff, int yOff, Pixmap src, int op)
2281     C_ARGS: term->display->dpy, dest, destKind, xOff, yOff, src, op
2282    
2283     void
2284     XShapeCombineShape (rxvt_term *term, XID dest, int destKind, int xOff, int yOff, Pixmap src, int srcKind, int op)
2285     C_ARGS: term->display->dpy, dest, destKind, xOff, yOff, src, srcKind, op
2286    
2287 root 1.79 Window
2288     rxvt_term::DefaultRootWindow ()
2289     CODE:
2290     RETVAL = THIS->display->root;
2291     OUTPUT:
2292     RETVAL
2293    
2294 root 1.81 #if 0
2295    
2296 root 1.79 Window
2297     XCreateSimpleWindow (rxvt_term *term, Window parent, int x, int y, unsigned int width, unsigned int height)
2298 root 1.96 C_ARGS: term->dpy, (Window)parent,
2299 root 1.79 x, y, width, height, 0,
2300     term->pix_colors_focused[Color_border],
2301     term->pix_colors_focused[Color_border]
2302    
2303 root 1.81 #endif
2304    
2305 root 1.79 void
2306     XReparentWindow (rxvt_term *term, Window window, Window parent, int x = 0, int y = 0)
2307 root 1.96 C_ARGS: term->dpy, window, parent, x, y
2308 root 1.79
2309     void
2310     XMapWindow (rxvt_term *term, Window window)
2311 root 1.96 C_ARGS: term->dpy, window
2312 root 1.79
2313     void
2314     XUnmapWindow (rxvt_term *term, Window window)
2315 root 1.96 C_ARGS: term->dpy, window
2316 root 1.79
2317     void
2318     XMoveResizeWindow (rxvt_term *term, Window window, int x, int y, unsigned int width, unsigned int height)
2319 root 1.96 C_ARGS: term->dpy, window, x, y, width, height
2320 root 1.84
2321     void
2322     rxvt_term::XChangeInput (Window window, U32 add_events, U32 del_events = 0)
2323     CODE:
2324     {
2325     XWindowAttributes attr;
2326 root 1.96 XGetWindowAttributes (THIS->dpy, window, &attr);
2327     XSelectInput (THIS->dpy, window, attr.your_event_mask | add_events & ~del_events);
2328 root 1.84 }
2329 root 1.79
2330 root 1.82 void
2331     rxvt_term::XTranslateCoordinates (Window src, Window dst, int x, int y)
2332     PPCODE:
2333     {
2334     int dx, dy;
2335     Window child;
2336    
2337 root 1.96 if (XTranslateCoordinates (THIS->dpy, src, dst, x, y, &dx, &dy, &child))
2338 root 1.82 {
2339     EXTEND (SP, 3);
2340 sf-exg 1.259 PUSHs (sv_2mortal (newSViv (dx)));
2341     PUSHs (sv_2mortal (newSViv (dy)));
2342     PUSHs (sv_2mortal (newSVuv (child)));
2343 root 1.82 }
2344     }
2345    
2346 root 1.79 #############################################################################
2347 root 1.158 # fancy bg bloatstuff (TODO: should be moved up somewhere)
2348    
2349 root 1.191 bool
2350     rxvt_term::has_render ()
2351     CODE:
2352     RETVAL = THIS->display->flags & DISPLAY_HAS_RENDER;
2353     OUTPUT:
2354     RETVAL
2355    
2356 root 1.165 void
2357 root 1.181 rxvt_term::background_geometry (bool border = false)
2358 root 1.165 PPCODE:
2359     EXTEND (SP, 4);
2360 root 1.181 PUSHs (sv_2mortal (newSViv (THIS->parent_x + (border ? THIS->window_vt_x : 0))));
2361     PUSHs (sv_2mortal (newSViv (THIS->parent_y + (border ? THIS->window_vt_y : 0))));
2362     PUSHs (sv_2mortal (newSViv (border ? THIS->vt_width : THIS->szHint.width )));
2363     PUSHs (sv_2mortal (newSViv (border ? THIS->vt_height : THIS->szHint.height)));
2364 root 1.165
2365 root 1.162 #if HAVE_IMG
2366    
2367     rxvt_img *
2368 root 1.199 rxvt_term::new_img (SV *format = &PL_sv_undef, int x = 0, int y = 0, int width = 1, int height = 1)
2369 root 1.162 CODE:
2370     XRenderPictFormat *f = SvOK (format)
2371 sf-exg 1.168 ? XRenderFindStandardFormat (THIS->dpy, SvIV (format))
2372     : XRenderFindVisualFormat (THIS->dpy, THIS->visual);
2373 root 1.196 RETVAL = new rxvt_img (THIS, f, x, y, width, height);
2374 root 1.189 RETVAL->alloc ();
2375 root 1.162 OUTPUT:
2376     RETVAL
2377    
2378 root 1.160 #if ENABLE_TRANSPARENCY
2379 root 1.158
2380 root 1.159 rxvt_img *
2381     rxvt_term::new_img_from_root ()
2382     CODE:
2383     RETVAL = rxvt_img::new_from_root (THIS);
2384     OUTPUT:
2385     RETVAL
2386    
2387     #endif
2388 root 1.158
2389     #if HAVE_PIXBUF
2390    
2391 root 1.159 rxvt_img *
2392     rxvt_term::new_img_from_file (octet_string filename)
2393     CODE:
2394     try
2395     {
2396     RETVAL = rxvt_img::new_from_file (THIS, filename);
2397     }
2398     catch (const class rxvt_failure_exception &e)
2399     {
2400     croak ("new_img_from_file failed");
2401     }
2402     OUTPUT:
2403     RETVAL
2404    
2405 root 1.158 #endif
2406    
2407 root 1.161 void
2408 root 1.245 rxvt_term::clr_background ()
2409     CODE:
2410     delete THIS->bg_img;
2411     THIS->bg_img = 0;
2412     THIS->bg_flags = rxvt_term::BG_NEEDS_REFRESH;
2413    
2414     void
2415 root 1.180 rxvt_term::set_background (rxvt_img *img, bool border = false)
2416 root 1.161 CODE:
2417 sf-exg 1.210 delete THIS->bg_img;
2418     THIS->bg_img = 0;
2419 root 1.245 THIS->bg_flags = rxvt_term::BG_NEEDS_REFRESH;
2420 root 1.161
2421 root 1.245 //if (img) // TODO: cannot be false, maybe allow and get rid of clr_background?
2422 root 1.161 {
2423 root 1.183 img = img->clone (); // own the img
2424    
2425     if (img->repeat != RepeatNormal) // X11 only supports RepeatNormal as bg pixmap
2426 root 1.206 img->sub_rect (0, 0,
2427     border ? THIS->vt_width : THIS->szHint.width,
2428     border ? THIS->vt_height : THIS->szHint.height)
2429     ->replace (img);
2430 root 1.187
2431     // just in case, should usually be a nop
2432     img->reify ()
2433     ->replace (img);
2434    
2435     img->convert_format (XRenderFindVisualFormat (THIS->dpy, THIS->visual), THIS->pix_colors [Color_bg])
2436     ->replace (img);
2437 root 1.186
2438 sf-exg 1.190 THIS->bg_img = img;
2439 root 1.180
2440     if (!border)
2441     THIS->bg_flags |= rxvt_term::BG_IS_TRANSPARENT;
2442 root 1.161 }
2443    
2444     #endif
2445    
2446 root 1.158 #############################################################################
2447 root 1.79 # urxvt::overlay
2448     #############################################################################
2449    
2450 root 1.13 MODULE = urxvt PACKAGE = urxvt::overlay
2451 root 1.1
2452     void
2453 root 1.13 overlay::set (int x, int y, SV *text, SV *rend = 0)
2454 root 1.1
2455     void
2456 root 1.18 overlay::show ()
2457    
2458     void
2459     overlay::hide ()
2460    
2461     void
2462 root 1.13 overlay::DESTROY ()
2463 root 1.1
2464 root 1.109 INCLUDE: $PERL <iom_perl.xs -pe s/IOM_MODULE/urxvt/g,s/IOM_CLASS/urxvt/g |
2465 root 1.1
2466 root 1.155 MODULE = urxvt PACKAGE = urxvt::pixbuf PREFIX = gdk_pixbuf_
2467    
2468 root 1.156 #if HAVE_PIXBUF
2469    
2470     urxvt::pixbuf gdk_pixbuf_new_from_file (SV *klass, octet_string filename)
2471     C_ARGS: filename, 0
2472 root 1.155
2473     void
2474     DESTROY (urxvt::pixbuf self)
2475     CODE:
2476 sf-exg 1.201 g_object_unref (self);
2477 root 1.155
2478 root 1.156 #endif
2479    
2480     MODULE = urxvt PACKAGE = urxvt::img
2481    
2482     #if HAVE_IMG
2483    
2484 root 1.158 # rxvt_img *new (rxvt_screen *screen, XRenderPictFormat *format, int width, int height)
2485     # rxvt_img *rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int width, int height, Pixmap pixmap);
2486 root 1.156
2487 root 1.196 void
2488     rxvt_img::geometry ()
2489     PPCODE:
2490     EXTEND (SP, 4);
2491     PUSHs (sv_2mortal (newSViv (THIS->x)));
2492     PUSHs (sv_2mortal (newSViv (THIS->y)));
2493     PUSHs (sv_2mortal (newSViv (THIS->w)));
2494     PUSHs (sv_2mortal (newSViv (THIS->h)));
2495    
2496     int
2497     rxvt_img::x ()
2498 root 1.200 ALIAS:
2499     x = 0
2500     y = 1
2501     w = 2
2502     h = 3
2503     CODE:
2504     switch (ix)
2505     {
2506     case 0: RETVAL = THIS->x; break;
2507     case 1: RETVAL = THIS->y; break;
2508     case 2: RETVAL = THIS->w; break;
2509     case 3: RETVAL = THIS->h; break;
2510     }
2511 root 1.162 OUTPUT:
2512     RETVAL
2513    
2514     Pixmap
2515     rxvt_img::pm ()
2516     CODE:
2517     RETVAL = THIS->pm;
2518     OUTPUT:
2519     RETVAL
2520    
2521 root 1.158 void
2522 root 1.204 rxvt_img::fill (SV *c, int x = 0, int y = 0, int w = THIS->w, int h = THIS->h)
2523     PROTOTYPE: $;$$$$
2524 root 1.158 INIT:
2525 sf-exg 1.242 rxvt_screen screen;
2526     screen.set (THIS->d);
2527     rgba cc = parse_rgba (c, &screen);
2528 root 1.204 C_ARGS: cc, x, y, w, h
2529 root 1.156
2530 root 1.158 void
2531 root 1.159 rxvt_img::DESTROY ()
2532     CODE:
2533     delete THIS;
2534    
2535 root 1.176 void
2536 root 1.200 rxvt_img::add_alpha ()
2537    
2538     void
2539 root 1.176 rxvt_img::unshare ()
2540    
2541 root 1.200 void
2542 root 1.183 rxvt_img::repeat_mode (render_repeat_mode repeat = 0)
2543 root 1.200 PPCODE:
2544 root 1.183 if (items >= 2)
2545     THIS->repeat_mode (repeat);
2546     if (GIMME_V != G_VOID)
2547     XPUSHs (sv_2mortal (newSViv (THIS->repeat)));
2548 root 1.176
2549     void
2550     rxvt_img::move (int dx, int dy)
2551 root 1.156
2552 root 1.158 void
2553 root 1.197 rxvt_img::brightness (rxvt_img::nv r, rxvt_img::nv g, rxvt_img::nv b, rxvt_img::nv a = 1.)
2554 root 1.159
2555     void
2556 root 1.197 rxvt_img::contrast (rxvt_img::nv r, rxvt_img::nv g, rxvt_img::nv b, rxvt_img::nv a = 1.)
2557 root 1.156
2558 root 1.199 void
2559     rxvt_img::draw (rxvt_img *img, int op = PictOpOver, rxvt_img::nv mask = 1.);
2560    
2561 root 1.176 rxvt_img *
2562     rxvt_img::clone ()
2563 root 1.156
2564 root 1.158 rxvt_img *
2565 root 1.178 rxvt_img::reify ()
2566    
2567     rxvt_img *
2568 root 1.176 rxvt_img::sub_rect (int x, int y, int width, int height)
2569 root 1.156
2570 root 1.158 rxvt_img *
2571 root 1.176 rxvt_img::blur (int rh, int rv)
2572 root 1.167
2573     rxvt_img *
2574 root 1.205 rxvt_img::muladd (rxvt_img::nv mul, rxvt_img::nv add)
2575    
2576     rxvt_img *
2577 root 1.197 rxvt_img::transform (rxvt_img::nv p11, rxvt_img::nv p12, rxvt_img::nv p13, rxvt_img::nv p21, rxvt_img::nv p22, rxvt_img::nv p23, rxvt_img::nv p31, rxvt_img::nv p32, rxvt_img::nv p33)
2578 root 1.159 INIT:
2579 root 1.197 rxvt_img::nv matrix[3][3] = {
2580 root 1.193 { p11, p12, p13 },
2581     { p21, p22, p23 },
2582     { p31, p32, p33 }
2583 root 1.159 };
2584 root 1.193 C_ARGS: matrix
2585 root 1.156
2586 root 1.164 rxvt_img *
2587     rxvt_img::scale (int new_width, int new_height)
2588    
2589     rxvt_img *
2590 root 1.197 rxvt_img::rotate (int x, int y, rxvt_img::nv phi)
2591 root 1.164
2592 root 1.203 rxvt_img *
2593 root 1.200 rxvt_img::tint (SV *c)
2594     INIT:
2595 sf-exg 1.242 rxvt_screen screen;
2596     screen.set (THIS->d);
2597     rgba cc = parse_rgba (c, &screen);
2598 root 1.200 C_ARGS: cc
2599    
2600     rxvt_img *
2601 sf-exg 1.212 rxvt_img::shade (rxvt_img::nv factor)
2602    
2603     rxvt_img *
2604 root 1.200 rxvt_img::filter (octet_string name, SV *params = &PL_sv_undef)
2605     CODE:
2606     rxvt_img::nv *vparams = 0;
2607     int nparams = 0;
2608    
2609     if (SvOK (params))
2610     {
2611     if (!SvROK (params) || SvTYPE (SvRV (params)) != SVt_PVAV)
2612     croak ("rxvt_img::filter: params must be an array reference with parameter values");
2613    
2614     nparams = av_len ((AV *)SvRV (params)) + 1;
2615 sf-exg 1.214 vparams = (rxvt_img::nv *)malloc (nparams * sizeof (rxvt_img::nv));
2616 root 1.200
2617     for (int i = 0; i < nparams; ++i)
2618     vparams [i] = SvNV (*av_fetch ((AV *)SvRV (params), i, 1));
2619     }
2620    
2621     RETVAL = THIS->filter (name, nparams, vparams);
2622 sf-exg 1.214 free (vparams);
2623 root 1.200 OUTPUT:
2624     RETVAL
2625    
2626 root 1.156 #endif
2627