--- rxvt-unicode/src/rxvtperl.xs 2010/02/14 19:34:42 1.130 +++ rxvt-unicode/src/rxvtperl.xs 2012/06/03 18:04:44 1.158 @@ -3,7 +3,7 @@ *----------------------------------------------------------------------* * * All portions of code are copyright by their respective author/s. - * Copyright (c) 2005-2008 Marc Lehmann + * Copyright (c) 2005-2008,2011 Marc Lehmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,11 +25,12 @@ #include #include #undef line_t +#undef bool // perl defines it's own bool type, except with g++... what a trap #include "../config.h" -#include -#include +#include +#include #include "unistd.h" @@ -50,6 +51,23 @@ ///////////////////////////////////////////////////////////////////////////// +typedef char * octet_string; +typedef char * utf8_string; + +typedef GdkPixbuf * urxvt__pixbuf; +typedef rxvt_img * urxvt__img; + +///////////////////////////////////////////////////////////////////////////// + +static void +parse_color (rxvt_screen *s, rxvt_color &c, SV *sv) +{ + //TODO: support component stuff + c.set (s, SvPVbyte_nolen (sv)); +} + +///////////////////////////////////////////////////////////////////////////// + static wchar_t * sv2wcs (SV *sv) { @@ -304,8 +322,6 @@ ///////////////////////////////////////////////////////////////////////////// -#define IOM_CLASS "urxvt" -#define IOM_WARN rxvt_warn #include "iom_perl.h" ///////////////////////////////////////////////////////////////////////////// @@ -331,37 +347,37 @@ { rxvt_push_locale (""); // perl init destroys current locale - perl_environ = rxvt_environ; - swap (perl_environ, environ); + { + perl_environ = rxvt_environ; + localise_env set_environ (perl_environ); - char *args[] = { - "", - "-e" - "BEGIN {" - " urxvt->bootstrap;" - " unshift @INC, '" LIBDIR "';" - "}" - "" - "use urxvt;" - }; - int argc = sizeof (args) / sizeof (args[0]); - char **argv = args; - - PERL_SYS_INIT3 (&argc, &argv, &environ); - perl = perl_alloc (); - perl_construct (perl); + char *args[] = { + "", + "-e" + "BEGIN {" + " urxvt->bootstrap;" + " unshift @INC, '" LIBDIR "';" + "}" + "" + "use urxvt;" + }; + int argc = ecb_array_length (args); + char **argv = args; - if (perl_parse (perl, xs_init, argc, argv, (char **)NULL) - || perl_run (perl)) - { - rxvt_warn ("unable to initialize perl-interpreter, continuing without.\n"); + PERL_SYS_INIT3 (&argc, &argv, &environ); + perl = perl_alloc (); + perl_construct (perl); - perl_destruct (perl); - perl_free (perl); - perl = 0; - } + if (perl_parse (perl, xs_init, argc, argv, (char **)NULL) + || perl_run (perl)) + { + rxvt_warn ("unable to initialize perl-interpreter, continuing without.\n"); - swap (perl_environ, environ); + perl_destruct (perl); + perl_free (perl); + perl = 0; + } + } rxvt_pop_locale (); } @@ -371,6 +387,7 @@ // runs outside of perls ENV term->perl.self = (void *)newSVptr ((void *)term, "urxvt::term"); hv_store ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, newRV_noinc ((SV *)newAV ()), 0); + hv_store ((HV *)SvRV ((SV *)term->perl.self), "_selection", 10, newRV_noinc ((SV *)newAV ()), 0); } } @@ -391,6 +408,8 @@ if (!perl || !term->perl.self) return false; + localise_env set_environ (perl_environ); + // pre-handling of some events if (htype == HOOK_REFRESH_END) { @@ -399,204 +418,207 @@ for (int i = 0; i <= AvFILL (av); i++) ((overlay *)SvIV (*av_fetch (av, i, 0)))->swap (); } + else if (htype == HOOK_DESTROY) + { + AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_selection", 10, 0)); - swap (perl_environ, environ); + for (int i = AvFILL (av); i >= 0; i--) + { + rxvt_selection *req = (rxvt_selection *)SvIV (*av_fetch (av, i, 0)); + delete req; + } + } bool event_consumed; if (htype == HOOK_INIT || htype == HOOK_DESTROY // must be called always || term->perl.should_invoke [htype]) - try - { - dSP; - va_list ap; + { + dSP; + va_list ap; - va_start (ap, htype); + va_start (ap, htype); - ENTER; - SAVETMPS; + ENTER; + SAVETMPS; - PUSHMARK (SP); + PUSHMARK (SP); - XPUSHs (sv_2mortal (newSVterm (term))); - XPUSHs (sv_2mortal (newSViv (htype))); + EXTEND (SP, 2); + PUSHs (sv_2mortal (newSVterm (term))); + PUSHs (sv_2mortal (newSViv (htype))); - for (;;) { - data_type dt = (data_type)va_arg (ap, int); + for (;;) { + data_type dt = (data_type)va_arg (ap, int); - switch (dt) - { - case DT_INT: - XPUSHs (sv_2mortal (newSViv (va_arg (ap, int)))); - break; - - case DT_LONG: - XPUSHs (sv_2mortal (newSViv (va_arg (ap, long)))); - break; - - case DT_STR: - XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0))); - break; + switch (dt) + { + case DT_INT: + XPUSHs (sv_2mortal (newSViv (va_arg (ap, int)))); + break; - case DT_STR_LEN: - { - char *str = va_arg (ap, char *); - int len = va_arg (ap, int); + case DT_LONG: + XPUSHs (sv_2mortal (newSViv (va_arg (ap, long)))); + break; - XPUSHs (sv_2mortal (newSVpvn (str, len))); - } - break; + case DT_STR: + XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0))); + break; - case DT_WCS_LEN: - { - wchar_t *wstr = va_arg (ap, wchar_t *); - int wlen = va_arg (ap, int); + case DT_STR_LEN: + { + char *str = va_arg (ap, char *); + int len = va_arg (ap, int); - XPUSHs (sv_2mortal (wcs2sv (wstr, wlen))); - } - break; + XPUSHs (sv_2mortal (newSVpvn (str, len))); + } + break; - case DT_LCS_LEN: - { - long *lstr = va_arg (ap, long *); - int llen = va_arg (ap, int); + case DT_WCS_LEN: + { + wchar_t *wstr = va_arg (ap, wchar_t *); + int wlen = va_arg (ap, int); - XPUSHs (sv_2mortal (newSVpvn ((char *)lstr, llen * sizeof (long)))); - } - break; + XPUSHs (sv_2mortal (wcs2sv (wstr, wlen))); + } + break; - case DT_XEVENT: - { - XEvent *xe = va_arg (ap, XEvent *); - HV *hv = newHV (); + case DT_LCS_LEN: + { + long *lstr = va_arg (ap, long *); + int llen = va_arg (ap, int); -# define set(name, sv) hv_store (hv, # name, sizeof (# name) - 1, sv, 0) -# define setiv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSViv (val), 0) -# define setuv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSVuv (val), 0) -# undef set - - setiv (type, xe->type); - setiv (send_event, xe->xany.send_event); - setiv (serial, xe->xany.serial); - - switch (xe->type) - { - case KeyPress: - case KeyRelease: - case ButtonPress: - case ButtonRelease: - case MotionNotify: - setuv (window, xe->xmotion.window); - setuv (root, xe->xmotion.root); - setuv (subwindow, xe->xmotion.subwindow); - setuv (time, xe->xmotion.time); - setiv (x, xe->xmotion.x); - setiv (y, xe->xmotion.y); - setiv (row, xe->xmotion.y / term->fheight + term->view_start); - setiv (col, xe->xmotion.x / term->fwidth); - setiv (x_root, xe->xmotion.x_root); - setiv (y_root, xe->xmotion.y_root); - setuv (state, xe->xmotion.state); - - switch (xe->type) - { - case KeyPress: - case KeyRelease: - setuv (keycode, xe->xkey.keycode); - break; - - case ButtonPress: - case ButtonRelease: - setuv (button, xe->xbutton.button); - break; - - case MotionNotify: - setiv (is_hint, xe->xmotion.is_hint); - break; - } - - break; - - case MapNotify: - case UnmapNotify: - case ConfigureNotify: - setuv (event, xe->xconfigure.event); - setuv (window, xe->xconfigure.window); - - switch (xe->type) - { - case ConfigureNotify: - setiv (x, xe->xconfigure.x); - setiv (y, xe->xconfigure.y); - setiv (width, xe->xconfigure.width); - setiv (height, xe->xconfigure.height); - setuv (above, xe->xconfigure.above); - break; - } - - break; - - case PropertyNotify: - setuv (window, xe->xproperty.window); - setuv (atom, xe->xproperty.atom); - setuv (time, xe->xproperty.time); - setiv (state, xe->xproperty.state); - break; - - case ClientMessage: - setuv (window, xe->xclient.window); - setuv (message_type, xe->xclient.message_type); - setuv (format, xe->xclient.format); - setuv (l0, xe->xclient.data.l[0]); - setuv (l1, xe->xclient.data.l[1]); - setuv (l2, xe->xclient.data.l[2]); - setuv (l3, xe->xclient.data.l[3]); - setuv (l4, xe->xclient.data.l[4]); - break; - } + XPUSHs (sv_2mortal (newSVpvn ((char *)lstr, llen * sizeof (long)))); + } + break; - XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv))); - } - break; + case DT_XEVENT: + { + XEvent *xe = va_arg (ap, XEvent *); + HV *hv = newHV (); - case DT_END: - goto call; +# define set(name, sv) hv_store (hv, # name, sizeof (# name) - 1, sv, 0) +# define setiv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSViv (val), 0) +# define setuv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSVuv (val), 0) +# undef set + + setiv (type, xe->type); + setiv (send_event, xe->xany.send_event); + setiv (serial, xe->xany.serial); - default: - rxvt_fatal ("FATAL: unable to pass data type %d\n", dt); - } - } + switch (xe->type) + { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + case MotionNotify: + setuv (window, xe->xmotion.window); + setuv (root, xe->xmotion.root); + setuv (subwindow, xe->xmotion.subwindow); + setuv (time, xe->xmotion.time); + setiv (x, xe->xmotion.x); + setiv (y, xe->xmotion.y); + setiv (row, xe->xmotion.y / term->fheight + term->view_start); + setiv (col, xe->xmotion.x / term->fwidth); + setiv (x_root, xe->xmotion.x_root); + setiv (y_root, xe->xmotion.y_root); + setuv (state, xe->xmotion.state); + + switch (xe->type) + { + case KeyPress: + case KeyRelease: + setuv (keycode, xe->xkey.keycode); + break; + + case ButtonPress: + case ButtonRelease: + setuv (button, xe->xbutton.button); + break; + + case MotionNotify: + setiv (is_hint, xe->xmotion.is_hint); + break; + } + + break; + + case MapNotify: + case UnmapNotify: + case ConfigureNotify: + setuv (event, xe->xconfigure.event); + setuv (window, xe->xconfigure.window); + + switch (xe->type) + { + case ConfigureNotify: + setiv (x, xe->xconfigure.x); + setiv (y, xe->xconfigure.y); + setiv (width, xe->xconfigure.width); + setiv (height, xe->xconfigure.height); + setuv (above, xe->xconfigure.above); + break; + } + + break; + + case PropertyNotify: + setuv (window, xe->xproperty.window); + setuv (atom, xe->xproperty.atom); + setuv (time, xe->xproperty.time); + setiv (state, xe->xproperty.state); + break; + + case ClientMessage: + setuv (window, xe->xclient.window); + setuv (message_type, xe->xclient.message_type); + setuv (format, xe->xclient.format); + setuv (l0, xe->xclient.data.l[0]); + setuv (l1, xe->xclient.data.l[1]); + setuv (l2, xe->xclient.data.l[2]); + setuv (l3, xe->xclient.data.l[3]); + setuv (l4, xe->xclient.data.l[4]); + break; + } - call: - va_end (ap); + XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv))); + } + break; - PUTBACK; - int count = call_pv ("urxvt::invoke", G_ARRAY | G_EVAL); - SPAGAIN; + case DT_END: + goto call; - if (count) - { - SV *status = POPs; - count = SvTRUE (status); + default: + rxvt_fatal ("FATAL: unable to pass data type %d\n", dt); } + } - PUTBACK; - FREETMPS; - LEAVE; + call: + va_end (ap); - if (SvTRUE (ERRSV)) - { - rxvt_warn ("perl hook %d evaluation error: %s", htype, SvPV_nolen (ERRSV)); - ungrab (term); // better lose the grab than the session - } + PUTBACK; + int count = call_pv ("urxvt::invoke", G_ARRAY | G_EVAL); + SPAGAIN; - event_consumed = !!count; - } - catch (...) - { - swap (perl_environ, environ); - throw; - } + if (count) + { + SV *status = POPs; + count = SvTRUE (status); + } + + PUTBACK; + FREETMPS; + LEAVE; + + if (SvTRUE (ERRSV)) + { + rxvt_warn ("perl hook %d evaluation error: %s", htype, SvPVbyte_nolen (ERRSV)); + ungrab (term); // better lose the grab than the session + } + + event_consumed = !!count; + } else event_consumed = false; @@ -617,11 +639,28 @@ term->perl.self = 0; } - swap (perl_environ, environ); - return event_consumed; } +void +rxvt_perl_interp::selection_finish (rxvt_selection *sel, char *data, unsigned int len) +{ + localise_env set_environ (perl_environ); + + ENTER; + SAVETMPS; + + dSP; + XPUSHs (sv_2mortal (newSVpvn (data, len))); + call_sv ((SV *)sel->cb_sv, G_VOID | G_DISCARD | G_EVAL); + + if (SvTRUE (ERRSV)) + rxvt_warn ("perl selection callback evaluation error: %s", SvPVbyte_nolen (ERRSV)); + + FREETMPS; + LEAVE; +} + ///////////////////////////////////////////////////////////////////////////// MODULE = urxvt PACKAGE = urxvt @@ -641,7 +680,7 @@ # undef def HV *option = get_hv ("urxvt::OPTION", 1); -# define def(name,val) hv_store (option, # name, sizeof (# name) - 1, newSVuv (Opt_ ## name), 0); +# define def(name) hv_store (option, # name, sizeof (# name) - 1, newSVuv (Opt_ ## name), 0); # define nodef(name) # include "optinc.h" # undef nodef @@ -656,6 +695,17 @@ const_iv (NUM_RESOURCES), const_iv (DEFAULT_RSTYLE), const_iv (OVERLAY_RSTYLE), + const_iv (Color_Bits), + const_iv (RS_bgShift), const_iv (RS_bgMask), + const_iv (RS_fgShift), const_iv (RS_fgMask), + const_iv (RS_Careful), + const_iv (RS_fontCount), + const_iv (RS_fontShift), + const_iv (RS_fontMask), + const_iv (RS_baseattrMask), + const_iv (RS_attrMask), + const_iv (RS_redraw), + const_iv (RS_Sel), const_iv (RS_Bold), const_iv (RS_Italic), const_iv (RS_Blink), @@ -752,6 +802,13 @@ const_iv (XIMVisibleToForward), const_iv (XIMVisibleToBackword), const_iv (XIMVisibleToCenter), +#if HAVE_XRENDER + const_iv (PictStandardARGB32), + const_iv (PictStandardRGB24), + const_iv (PictStandardA8), + const_iv (PictStandardA4), + const_iv (PictStandardA1), +#endif # if 0 const_iv (XIMForwardChar), const_iv (XIMBackwardChar), @@ -769,8 +826,8 @@ # endif }; - for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) - newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); + for (civ = const_iv + ecb_array_length (const_iv); civ > const_iv; civ--) + newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv)); } void @@ -852,6 +909,35 @@ PUSHs (sv_2mortal (newSVterm (*t))); } +IV +_new_selection_request (rxvt_term *term, int selnum, Time tm, Window win, Atom prop, SV *cb) + CODE: + rxvt_selection *req = new rxvt_selection (term->display, selnum, tm, win, prop, term); + req->cb_sv = newSVsv (cb); + AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_selection", 10, 0)); + av_push (av, newSViv ((IV)req)); + RETVAL = (IV)req; + OUTPUT: + RETVAL + +void +_delete_selection_request (IV req_) + CODE: + rxvt_selection *req = (rxvt_selection *)req_; + AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)req->term->perl.self), "_selection", 10, 0)); + int i; + + for (i = AvFILL (av); i >= 0; i--) + if (SvIV (*av_fetch (av, i, 1)) == req_) + break; + + for (; i < AvFILL (av); i++) + av_store (av, i, SvREFCNT_inc (*av_fetch (av, i + 1, 0))); + + av_pop (av); + + delete req; + MODULE = urxvt PACKAGE = urxvt::term SV * @@ -861,16 +947,13 @@ rxvt_term *term = new rxvt_term; stringvec *argv = new stringvec; - stringvec *envv = new stringvec; - for (int i = 0; i <= AvFILL (arg); i++) argv->push_back (strdup (SvPVbyte_nolen (*av_fetch (arg, i, 1)))); + stringvec *envv = new stringvec; for (int i = AvFILL (env) + 1; i--; ) envv->push_back (strdup (SvPVbyte_nolen (*av_fetch (env, i, 1)))); - envv->push_back (0); - try { term->init (argv, envv); @@ -920,11 +1003,6 @@ CODE: XUngrabKey (THIS->dpy, keycode, modifiers, window); -void -rxvt_term::XUngrabKeyboard (Time eventtime) - CODE: - XUngrabKeyboard (THIS->dpy, eventtime); - bool rxvt_term::grab (Time eventtime, int sync = 0) CODE: @@ -1048,13 +1126,6 @@ OUTPUT: RETVAL -char * -rxvt_term::locale () - CODE: - RETVAL = THIS->locale; - OUTPUT: - RETVAL - #define TERM_OFFSET(sym) offsetof (TermWin_t, sym) #define TERM_OFFSET_width TERM_OFFSET(width) @@ -1168,7 +1239,7 @@ Window rxvt_term::parent () CODE: - RETVAL = THIS->parent [0]; + RETVAL = THIS->parent; OUTPUT: RETVAL @@ -1207,6 +1278,9 @@ RETVAL void +rxvt_term::set_urgency (bool enable) + +void rxvt_term::focus_in () void @@ -1447,7 +1521,7 @@ # undef reserve }; - rs = rslist + sizeof (rslist) / sizeof (rslist [0]); + rs = rslist + ecb_array_length (rslist); if (*name) { @@ -1496,7 +1570,7 @@ { THIS->set_option (optval, set); - if (THIS->env_colorfgbg [0]) // avoid doing this before START + if (THIS->init_done) // avoid doing this before START switch (optval) { case Opt_skipBuiltinGlyphs: @@ -1506,6 +1580,11 @@ THIS->want_refresh = 1; THIS->refresh_check (); break; +#ifdef CURSOR_BLINK + case Opt_cursorBlink: + THIS->cursor_blink_reset (); + break; +#endif case Opt_cursorUnderline: THIS->want_refresh = 1; @@ -1531,6 +1610,13 @@ RETVAL void +rxvt_term::register_command (int keysym, unsigned int state, SV *str) + CODE: + wchar_t *wstr = sv2wcs (str); + THIS->keyboard->register_user_translation (keysym, state, wstr); + free (wstr); + +void rxvt_term::screen_cur (...) PROTOTYPE: $;$$ ALIAS: @@ -1666,6 +1752,14 @@ str, len void +rxvt_term::tt_paste (SV *octets) + INIT: + STRLEN len; + char *str = SvPVbyte (octets, len); + C_ARGS: + str, len + +void rxvt_term::cmd_parse (SV *octets) CODE: { @@ -1833,6 +1927,24 @@ } ############################################################################# +# fancy bg bloatstuff (TODO: should be moved up somewhere) + +#ifdef ENABLE_TRANSPARENCY + +# rxvt_img * +# rxvt_term::new_root_img () +# CODE: +# RETVAL = rxvt_img::new_from_root (THIS); +# OUTPUT: +# RETVAL + +#endif + +#if HAVE_PIXBUF + +#endif + +############################################################################# # urxvt::overlay ############################################################################# @@ -1852,3 +1964,51 @@ INCLUDE: $PERL s, rc, c); + C_ARGS: rc + +void +rxvt_img::blur (int rh, int rv) + +void +rxvt_img::brightness (double r, double g, double b, double a = 1.) + +void +rxvt_img::contrast (double r, double g, double b, double a = 1.) + +rxvt_img * +rxvt_img::copy () + +rxvt_img * +rxvt_img::scale (int new_width, int new_height) + +# rxvt_img * +# rxvt_img::transform (int new_width, int new_height, double matrix[16]); + +#endif +