ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvtperl.xs
(Generate patch)

Comparing rxvt-unicode/src/rxvtperl.xs (file contents):
Revision 1.69 by root, Mon Jan 16 15:00:20 2006 UTC vs.
Revision 1.76 by root, Thu Jan 19 11:56:00 2006 UTC

54 54
55#define ENABLE_PERL_FRILLS 1 55#define ENABLE_PERL_FRILLS 1
56 56
57///////////////////////////////////////////////////////////////////////////// 57/////////////////////////////////////////////////////////////////////////////
58 58
59static SV *
60taint (SV *sv)
61{
62 SvTAINT (sv);
63 return sv;
64}
65
66static SV *
67taint_if (SV *sv, SV *src)
68{
69 if (SvTAINTED (src))
70 SvTAINT (sv);
71
72 return sv;
73}
74
75static wchar_t * 59static wchar_t *
76sv2wcs (SV *sv) 60sv2wcs (SV *sv)
77{ 61{
78 STRLEN len; 62 STRLEN len;
79 char *str = SvPVutf8 (sv, len); 63 char *str = SvPVutf8 (sv, len);
227 211
228#define SvOVERLAY(sv) (overlay *)SvPTR (sv, "urxvt::overlay") 212#define SvOVERLAY(sv) (overlay *)SvPTR (sv, "urxvt::overlay")
229 213
230struct overlay { 214struct overlay {
231 HV *self; 215 HV *self;
216 bool visible;
232 rxvt_term *THIS; 217 rxvt_term *THIS;
233 int x, y, w, h; 218 int x, y, w, h;
234 int border; 219 int border;
235 text_t **text; 220 text_t **text;
236 rend_t **rend; 221 rend_t **rend;
245 230
246 void set (int x, int y, SV *str, SV *rend); 231 void set (int x, int y, SV *str, SV *rend);
247}; 232};
248 233
249overlay::overlay (rxvt_term *THIS, int x_, int y_, int w_, int h_, rend_t rstyle, int border) 234overlay::overlay (rxvt_term *THIS, int x_, int y_, int w_, int h_, rend_t rstyle, int border)
250: THIS(THIS), x(x_), y(y_), w(w_), h(h_), border(border == 2) 235: THIS(THIS), x(x_), y(y_), w(w_), h(h_), border(border == 2), visible(false)
251{ 236{
252 if (border == 2) 237 if (border == 2)
253 { 238 {
254 w += 2; 239 w += 2;
255 h += 2; 240 h += 2;
316} 301}
317 302
318void 303void
319overlay::show () 304overlay::show ()
320{ 305{
321 char key[33]; sprintf (key, "%32lx", (long)this); 306 if (visible)
307 return;
322 308
309 visible = true;
310
323 HV *hv = (HV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)THIS->perl.self), "_overlay", 8, 0)); 311 AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)THIS->perl.self), "_overlay", 8, 0));
324 hv_store (hv, key, 32, newSViv ((long)this), 0); 312 av_push (av, newSViv ((long)this));
325} 313}
326 314
327void 315void
328overlay::hide () 316overlay::hide ()
329{ 317{
318 if (!visible)
319 return;
320
321 visible = false;
322
330 SV **ovs = hv_fetch ((HV *)SvRV ((SV *)THIS->perl.self), "_overlay", 8, 0); 323 AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)THIS->perl.self), "_overlay", 8, 0));
331 324
332 if (ovs) 325 int i;
326
327 for (i = AvFILL (av); i >= 0; i--)
328 if (SvIV (*av_fetch (av, i, 1)) == (long)this)
333 { 329 {
334 char key[33]; sprintf (key, "%32lx", (long)this);
335
336 HV *hv = (HV *)SvRV (*ovs);
337 hv_delete (hv, key, 32, G_DISCARD); 330 av_delete (av, i, G_DISCARD);
331 break;
338 } 332 }
333
334 for (; i < AvFILL (av); i++)
335 av_store (av, i, SvREFCNT_inc (*av_fetch (av, i + 1, 0)));
336
337 av_pop (av);
339} 338}
340 339
341void overlay::swap () 340void overlay::swap ()
342{ 341{
343 int ov_x = max (0, min (MOD (x, THIS->ncol), THIS->ncol - w)); 342 int ov_x = max (0, min (MOD (x, THIS->ncol), THIS->ncol - w));
383 if (!SvROK (rend) || SvTYPE (SvRV (rend)) != SVt_PVAV) 382 if (!SvROK (rend) || SvTYPE (SvRV (rend)) != SVt_PVAV)
384 croak ("rend must be arrayref"); 383 croak ("rend must be arrayref");
385 384
386 AV *av = (AV *)SvRV (rend); 385 AV *av = (AV *)SvRV (rend);
387 386
388 for (int col = min (av_len (av) + 1, w - x - border); col--; ) 387 for (int col = min (AvFILL (av) + 1, w - x - border); col--; )
389 this->rend [y][x + col] = SvIV (*av_fetch (av, col, 1)); 388 this->rend [y][x + col] = SvIV (*av_fetch (av, col, 1));
390 } 389 }
391 390
392 THIS->want_refresh = 1; 391 THIS->want_refresh = 1;
393} 392}
418 perl_environ = rxvt_environ; 417 perl_environ = rxvt_environ;
419 swap (perl_environ, environ); 418 swap (perl_environ, environ);
420 419
421 char *argv[] = { 420 char *argv[] = {
422 "", 421 "",
423 "-T", 422 "-e"
424 "-edo '" LIBDIR "/urxvt.pm' or ($@ and die $@) or exit 1", 423 "BEGIN {"
424 " urxvt->bootstrap;"
425 " unshift @INC, '" LIBDIR "';"
426 "}"
427 ""
428 "use urxvt;"
425 }; 429 };
426 430
427 perl = perl_alloc (); 431 perl = perl_alloc ();
428 perl_construct (perl); 432 perl_construct (perl);
429 433
430 if (perl_parse (perl, xs_init, 3, argv, (char **)NULL) 434 if (perl_parse (perl, xs_init, 2, argv, (char **)NULL)
431 || perl_run (perl)) 435 || perl_run (perl))
432 { 436 {
433 rxvt_warn ("unable to initialize perl-interpreter, continuing without.\n"); 437 rxvt_warn ("unable to initialize perl-interpreter, continuing without.\n");
434 438
435 perl_destruct (perl); 439 perl_destruct (perl);
440 swap (perl_environ, environ); 444 swap (perl_environ, environ);
441 445
442 rxvt_pop_locale (); 446 rxvt_pop_locale ();
443 } 447 }
444 448
449 if (perl)
450 {
445 // runs outside of perls ENV 451 // runs outside of perls ENV
446 term->perl.self = (void *)newSVptr ((void *)term, "urxvt::term"); 452 term->perl.self = (void *)newSVptr ((void *)term, "urxvt::term");
447 hv_store ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, newRV_noinc ((SV *)newHV ()), 0); 453 hv_store ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, newRV_noinc ((SV *)newAV ()), 0);
454 }
448} 455}
449 456
450static void 457static void
451ungrab (rxvt_term *THIS) 458ungrab (rxvt_term *THIS)
452{ 459{
456 XUngrabPointer (THIS->display->display, THIS->perl.grabtime); 463 XUngrabPointer (THIS->display->display, THIS->perl.grabtime);
457 THIS->perl.grabtime = 0; 464 THIS->perl.grabtime = 0;
458 } 465 }
459} 466}
460 467
461static void
462swap_overlays (rxvt_term *term)
463{
464 HV *hv = (HV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, 0));
465
466 if (HvKEYS (hv))
467 {
468 hv_iterinit (hv);
469
470 while (HE *he = hv_iternext (hv))
471 ((overlay *)SvIV (hv_iterval (hv, he)))->swap ();
472 }
473}
474
475bool 468bool
476rxvt_perl_interp::invoke (rxvt_term *term, hook_type htype, ...) 469rxvt_perl_interp::invoke (rxvt_term *term, hook_type htype, ...)
477{ 470{
478 if (!perl || !term->perl.self) 471 if (!perl || !term->perl.self)
479 return false; 472 return false;
480 473
481 // pre-handling of some events 474 // pre-handling of some events
482 if (htype == HOOK_REFRESH_END) 475 if (htype == HOOK_REFRESH_END)
483 swap_overlays (term); 476 {
477 AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, 0));
478
479 for (int i = 0; i <= AvFILL (av); i++)
480 ((overlay *)SvIV (*av_fetch (av, i, 0)))->swap ();
481 }
484 482
485 swap (perl_environ, environ); 483 swap (perl_environ, environ);
486 484
487 bool event_consumed; 485 bool event_consumed;
488 486
515 case DT_LONG: 513 case DT_LONG:
516 XPUSHs (sv_2mortal (newSViv (va_arg (ap, long)))); 514 XPUSHs (sv_2mortal (newSViv (va_arg (ap, long))));
517 break; 515 break;
518 516
519 case DT_STR: 517 case DT_STR:
520 XPUSHs (taint (sv_2mortal (newSVpv (va_arg (ap, char *), 0)))); 518 XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
521 break; 519 break;
522 520
523 case DT_STR_LEN: 521 case DT_STR_LEN:
524 { 522 {
525 char *str = va_arg (ap, char *); 523 char *str = va_arg (ap, char *);
526 int len = va_arg (ap, int); 524 int len = va_arg (ap, int);
527 525
528 XPUSHs (taint (sv_2mortal (newSVpvn (str, len)))); 526 XPUSHs (sv_2mortal (newSVpvn (str, len)));
529 } 527 }
530 break; 528 break;
531 529
532 case DT_WCS_LEN: 530 case DT_WCS_LEN:
533 { 531 {
534 wchar_t *wstr = va_arg (ap, wchar_t *); 532 wchar_t *wstr = va_arg (ap, wchar_t *);
535 int wlen = va_arg (ap, int); 533 int wlen = va_arg (ap, int);
536 534
537 XPUSHs (taint (sv_2mortal (wcs2sv (wstr, wlen)))); 535 XPUSHs (sv_2mortal (wcs2sv (wstr, wlen)));
538 } 536 }
539 break; 537 break;
540 538
541 case DT_XEVENT: 539 case DT_XEVENT:
542 { 540 {
543 XEvent *xe = va_arg (ap, XEvent *); 541 XEvent *xe = va_arg (ap, XEvent *);
544 HV *hv = newHV (); 542 HV *hv = newHV ();
545 543
546# define set(name, sv) hv_store (hv, # name, sizeof (# name) - 1, sv, 0) 544# define set(name, sv) hv_store (hv, # name, sizeof (# name) - 1, sv, 0)
547# define setiv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSViv (val), 0) 545# define setiv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSViv (val), 0)
546# define setuv(name, val) hv_store (hv, # name, sizeof (# name) - 1, newSVuv (val), 0)
548# undef set 547# undef set
549 548
550 setiv (type, xe->type); 549 setiv (type, xe->type);
551 setiv (send_event, xe->xany.send_event); 550 setiv (send_event, xe->xany.send_event);
552 setiv (serial, xe->xany.serial); 551 setiv (serial, xe->xany.serial);
556 case KeyPress: 555 case KeyPress:
557 case KeyRelease: 556 case KeyRelease:
558 case ButtonPress: 557 case ButtonPress:
559 case ButtonRelease: 558 case ButtonRelease:
560 case MotionNotify: 559 case MotionNotify:
560 setuv (window, xe->xmotion.window);
561 setuv (root, xe->xmotion.root);
562 setuv (subwindow, xe->xmotion.subwindow);
561 setiv (time, xe->xmotion.time); 563 setuv (time, xe->xmotion.time);
562 setiv (x, xe->xmotion.x); 564 setiv (x, xe->xmotion.x);
563 setiv (y, xe->xmotion.y); 565 setiv (y, xe->xmotion.y);
564 setiv (row, xe->xmotion.y / term->fheight); 566 setiv (row, xe->xmotion.y / term->fheight);
565 setiv (col, xe->xmotion.x / term->fwidth); 567 setiv (col, xe->xmotion.x / term->fwidth);
566 setiv (x_root, xe->xmotion.x_root); 568 setiv (x_root, xe->xmotion.x_root);
567 setiv (y_root, xe->xmotion.y_root); 569 setiv (y_root, xe->xmotion.y_root);
568 setiv (state, xe->xmotion.state); 570 setuv (state, xe->xmotion.state);
571
572 switch (xe->type)
573 {
574 case KeyPress:
575 case KeyRelease:
576 setuv (keycode, xe->xkey.keycode);
577 break;
578
579 case ButtonPress:
580 case ButtonRelease:
581 setuv (button, xe->xbutton.button);
582 break;
583
584 case MotionNotify:
585 setiv (is_hint, xe->xmotion.is_hint);
586 break;
587 }
588
569 break; 589 break;
570 }
571 590
591 case MapNotify:
592 case UnmapNotify:
593 case ConfigureNotify:
594 setuv (event, xe->xconfigure.event);
595 setuv (window, xe->xconfigure.window);
596
572 switch (xe->type) 597 switch (xe->type)
573 { 598 {
574 case KeyPress: 599 case ConfigureNotify:
575 case KeyRelease: 600 setiv (x, xe->xconfigure.x);
576 setiv (keycode, xe->xkey.keycode); 601 setiv (y, xe->xconfigure.y);
602 setiv (width, xe->xconfigure.width);
603 setiv (height, xe->xconfigure.height);
604 setuv (above, xe->xconfigure.above);
577 break; 605 break;
578
579 case ButtonPress:
580 case ButtonRelease:
581 setiv (button, xe->xbutton.button);
582 break; 606 }
583 607
584 case MotionNotify:
585 setiv (is_hint, xe->xmotion.is_hint);
586 break; 608 break;
587 } 609 }
588 610
589 XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv))); 611 XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
590 } 612 }
631 else 653 else
632 event_consumed = false; 654 event_consumed = false;
633 655
634 // post-handling of some events 656 // post-handling of some events
635 if (htype == HOOK_REFRESH_BEGIN) 657 if (htype == HOOK_REFRESH_BEGIN)
636 swap_overlays (term); 658 {
659 AV *av = (AV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, 0));
660
661 for (int i = AvFILL (av); i >= 0; i--)
662 ((overlay *)SvIV (*av_fetch (av, i, 0)))->swap ();
663 }
637 else if (htype == HOOK_DESTROY) 664 else if (htype == HOOK_DESTROY)
638 { 665 {
639 clearSVptr ((SV *)term->perl.self); 666 clearSVptr ((SV *)term->perl.self);
640 SvREFCNT_dec ((SV *)term->perl.self); 667 SvREFCNT_dec ((SV *)term->perl.self);
641 } 668 }
779void 806void
780fatal (const char *msg) 807fatal (const char *msg)
781 CODE: 808 CODE:
782 rxvt_fatal ("%s", msg); 809 rxvt_fatal ("%s", msg);
783 810
784SV *
785untaint (SV *sv)
786 CODE:
787 RETVAL = newSVsv (sv);
788 SvTAINTED_off (RETVAL);
789 OUTPUT:
790 RETVAL
791
792void 811void
793_exit (int status) 812_exit (int status)
794
795bool
796safe ()
797 CODE:
798 RETVAL = !rxvt_tainted ();
799 OUTPUT:
800 RETVAL
801 813
802NV 814NV
803NOW () 815NOW ()
804 CODE: 816 CODE:
805 RETVAL = NOW; 817 RETVAL = NOW;
870 882
871 for (int i = 1; i < items; i++) 883 for (int i = 1; i < items; i++)
872 term->argv->push_back (strdup (SvPVbyte_nolen (ST (i)))); 884 term->argv->push_back (strdup (SvPVbyte_nolen (ST (i))));
873 885
874 AV *envv = (AV *)SvRV (ST (0)); 886 AV *envv = (AV *)SvRV (ST (0));
875 for (int i = av_len (envv) + 1; i--; ) 887 for (int i = AvFILL (envv) + 1; i--; )
876 term->envv->push_back (strdup (SvPVbyte_nolen (*av_fetch (envv, i, 1)))); 888 term->envv->push_back (strdup (SvPVbyte_nolen (*av_fetch (envv, i, 1))));
877 889
878 term->envv->push_back (0); 890 term->envv->push_back (0);
879 891
880 bool success; 892 bool success;
1071 char *mbstr = rxvt_wcstombs (wstr); 1083 char *mbstr = rxvt_wcstombs (wstr);
1072 rxvt_pop_locale (); 1084 rxvt_pop_locale ();
1073 1085
1074 free (wstr); 1086 free (wstr);
1075 1087
1076 RETVAL = taint_if (newSVpv (mbstr, 0), str); 1088 RETVAL = newSVpv (mbstr, 0);
1077 free (mbstr); 1089 free (mbstr);
1078} 1090}
1079 OUTPUT: 1091 OUTPUT:
1080 RETVAL 1092 RETVAL
1081 1093
1088 1100
1089 rxvt_push_locale (THIS->locale); 1101 rxvt_push_locale (THIS->locale);
1090 wchar_t *wstr = rxvt_mbstowcs (data, len); 1102 wchar_t *wstr = rxvt_mbstowcs (data, len);
1091 rxvt_pop_locale (); 1103 rxvt_pop_locale ();
1092 1104
1093 RETVAL = taint_if (wcs2sv (wstr), octets); 1105 RETVAL = wcs2sv (wstr);
1094 free (wstr); 1106 free (wstr);
1095} 1107}
1096 OUTPUT: 1108 OUTPUT:
1097 RETVAL 1109 RETVAL
1098 1110
1250 wchar_t *wstr = new wchar_t [THIS->ncol]; 1262 wchar_t *wstr = new wchar_t [THIS->ncol];
1251 1263
1252 for (int col = 0; col < THIS->ncol; col++) 1264 for (int col = 0; col < THIS->ncol; col++)
1253 wstr [col] = l.t [col]; 1265 wstr [col] = l.t [col];
1254 1266
1255 XPUSHs (taint (sv_2mortal (wcs2sv (wstr, THIS->ncol)))); 1267 XPUSHs (sv_2mortal (wcs2sv (wstr, THIS->ncol)));
1256 1268
1257 delete [] wstr; 1269 delete [] wstr;
1258 } 1270 }
1259 1271
1260 if (new_text) 1272 if (new_text)
1303 { 1315 {
1304 if (!SvROK (new_rend) || SvTYPE (SvRV (new_rend)) != SVt_PVAV) 1316 if (!SvROK (new_rend) || SvTYPE (SvRV (new_rend)) != SVt_PVAV)
1305 croak ("new_rend must be arrayref"); 1317 croak ("new_rend must be arrayref");
1306 1318
1307 AV *av = (AV *)SvRV (new_rend); 1319 AV *av = (AV *)SvRV (new_rend);
1308 int len = min (av_len (av) + 1 - start_ofs, max_len); 1320 int len = min (AvFILL (av) + 1 - start_ofs, max_len);
1309 1321
1310 if (!IN_RANGE_INC (start_col, 0, THIS->ncol - len)) 1322 if (!IN_RANGE_INC (start_col, 0, THIS->ncol - len))
1311 croak ("new_rend array extends beyond horizontal margins"); 1323 croak ("new_rend array extends beyond horizontal margins");
1312 1324
1313 for (int col = start_col; col < start_col + len; col++) 1325 for (int col = start_col; col < start_col + len; col++)
1381 else 1393 else
1382 *r++ = *s; 1394 *r++ = *s;
1383 1395
1384 rxvt_pop_locale (); 1396 rxvt_pop_locale ();
1385 1397
1386 RETVAL = taint_if (wcs2sv (rstr, r - rstr), string); 1398 RETVAL = wcs2sv (rstr, r - rstr);
1387 1399
1388 delete [] rstr; 1400 delete [] rstr;
1389} 1401}
1390 OUTPUT: 1402 OUTPUT:
1391 RETVAL 1403 RETVAL
1417 else if (IS_COMPOSE (*s)) 1429 else if (IS_COMPOSE (*s))
1418 r += rxvt_composite.expand (*s, r); 1430 r += rxvt_composite.expand (*s, r);
1419 else 1431 else
1420 *r++ = *s; 1432 *r++ = *s;
1421 1433
1422 RETVAL = taint_if (wcs2sv (rstr, r - rstr), text); 1434 RETVAL = wcs2sv (rstr, r - rstr);
1423 1435
1424 delete [] rstr; 1436 delete [] rstr;
1425} 1437}
1426 OUTPUT: 1438 OUTPUT:
1427 RETVAL 1439 RETVAL
1449 1461
1450 if (!IN_RANGE_EXC (index, 0, NUM_RESOURCES)) 1462 if (!IN_RANGE_EXC (index, 0, NUM_RESOURCES))
1451 croak ("requested out-of-bound resource %s+%d,", name, index - rs->value); 1463 croak ("requested out-of-bound resource %s+%d,", name, index - rs->value);
1452 1464
1453 if (GIMME_V != G_VOID) 1465 if (GIMME_V != G_VOID)
1454 XPUSHs (THIS->rs [index] ? sv_2mortal (taint (newSVpv (THIS->rs [index], 0))) : &PL_sv_undef); 1466 XPUSHs (THIS->rs [index] ? sv_2mortal (newSVpv (THIS->rs [index], 0)) : &PL_sv_undef);
1455 1467
1456 if (newval) 1468 if (newval)
1457 { 1469 {
1458 if (SvOK (newval)) 1470 if (SvOK (newval))
1459 { 1471 {
1466 } 1478 }
1467} 1479}
1468 1480
1469const char * 1481const char *
1470rxvt_term::x_resource (const char *name) 1482rxvt_term::x_resource (const char *name)
1471 CLEANUP:
1472 SvTAINTED_on (ST (0));
1473 1483
1474bool 1484bool
1475rxvt_term::option (U32 optval, int set = -1) 1485rxvt_term::option (U32 optval, int set = -1)
1476 CODE: 1486 CODE:
1477{ 1487{
1537 PUSHs (sv_2mortal (newSViv (rc.col))); 1547 PUSHs (sv_2mortal (newSViv (rc.col)));
1538 } 1548 }
1539 1549
1540 if (items == 3) 1550 if (items == 3)
1541 { 1551 {
1552 rc.row = SvIV (ST (1));
1553 rc.col = SvIV (ST (2));
1554
1555 if (ix == 2 && rc.col == 0)
1556 {
1557 rc.row--;
1558 rc.col = THIS->ncol;
1559 }
1560
1561 clamp_it (rc.col, 0, THIS->ncol);
1542 rc.row = clamp (SvIV (ST (1)), THIS->top_row, THIS->nrow - 1); 1562 clamp_it (rc.row, THIS->top_row, THIS->nrow - 1);
1543 rc.col = clamp (SvIV (ST (2)), 0, THIS->ncol - 1);
1544 1563
1545 if (ix) 1564 if (ix)
1546 THIS->want_refresh = 1; 1565 THIS->want_refresh = 1;
1547 } 1566 }
1548} 1567}
1571rxvt_term::selection (SV *newtext = 0) 1590rxvt_term::selection (SV *newtext = 0)
1572 PPCODE: 1591 PPCODE:
1573{ 1592{
1574 if (GIMME_V != G_VOID) 1593 if (GIMME_V != G_VOID)
1575 XPUSHs (THIS->selection.text 1594 XPUSHs (THIS->selection.text
1576 ? taint (sv_2mortal (wcs2sv (THIS->selection.text, THIS->selection.len))) 1595 ? sv_2mortal (wcs2sv (THIS->selection.text, THIS->selection.len))
1577 : &PL_sv_undef); 1596 : &PL_sv_undef);
1578 1597
1579 if (newtext) 1598 if (newtext)
1580 { 1599 {
1581 free (THIS->selection.text); 1600 free (THIS->selection.text);
1707 RETVAL = THIS; 1726 RETVAL = THIS;
1708 OUTPUT: 1727 OUTPUT:
1709 RETVAL 1728 RETVAL
1710 1729
1711timer * 1730timer *
1731timer::after (NV delay)
1732 CODE:
1733 THIS->start (NOW + delay);
1734 OUTPUT:
1735 RETVAL
1736
1737timer *
1712timer::stop () 1738timer::stop ()
1713 CODE: 1739 CODE:
1714 THIS->stop (); 1740 THIS->stop ();
1715 RETVAL = THIS; 1741 RETVAL = THIS;
1716 OUTPUT: 1742 OUTPUT:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines