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.70 by root, Tue Jan 17 09:34:21 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);
444 448
445 if (perl) 449 if (perl)
446 { 450 {
447 // runs outside of perls ENV 451 // runs outside of perls ENV
448 term->perl.self = (void *)newSVptr ((void *)term, "urxvt::term"); 452 term->perl.self = (void *)newSVptr ((void *)term, "urxvt::term");
449 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);
450 } 454 }
451} 455}
452 456
453static void 457static void
454ungrab (rxvt_term *THIS) 458ungrab (rxvt_term *THIS)
459 XUngrabPointer (THIS->display->display, THIS->perl.grabtime); 463 XUngrabPointer (THIS->display->display, THIS->perl.grabtime);
460 THIS->perl.grabtime = 0; 464 THIS->perl.grabtime = 0;
461 } 465 }
462} 466}
463 467
464static void
465swap_overlays (rxvt_term *term)
466{
467 HV *hv = (HV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, 0));
468
469 if (HvKEYS (hv))
470 {
471 hv_iterinit (hv);
472
473 while (HE *he = hv_iternext (hv))
474 ((overlay *)SvIV (hv_iterval (hv, he)))->swap ();
475 }
476}
477
478bool 468bool
479rxvt_perl_interp::invoke (rxvt_term *term, hook_type htype, ...) 469rxvt_perl_interp::invoke (rxvt_term *term, hook_type htype, ...)
480{ 470{
481 if (!perl || !term->perl.self) 471 if (!perl || !term->perl.self)
482 return false; 472 return false;
483 473
484 // pre-handling of some events 474 // pre-handling of some events
485 if (htype == HOOK_REFRESH_END) 475 if (htype == HOOK_REFRESH_END)
486 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 }
487 482
488 swap (perl_environ, environ); 483 swap (perl_environ, environ);
489 484
490 bool event_consumed; 485 bool event_consumed;
491 486
518 case DT_LONG: 513 case DT_LONG:
519 XPUSHs (sv_2mortal (newSViv (va_arg (ap, long)))); 514 XPUSHs (sv_2mortal (newSViv (va_arg (ap, long))));
520 break; 515 break;
521 516
522 case DT_STR: 517 case DT_STR:
523 XPUSHs (taint (sv_2mortal (newSVpv (va_arg (ap, char *), 0)))); 518 XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
524 break; 519 break;
525 520
526 case DT_STR_LEN: 521 case DT_STR_LEN:
527 { 522 {
528 char *str = va_arg (ap, char *); 523 char *str = va_arg (ap, char *);
529 int len = va_arg (ap, int); 524 int len = va_arg (ap, int);
530 525
531 XPUSHs (taint (sv_2mortal (newSVpvn (str, len)))); 526 XPUSHs (sv_2mortal (newSVpvn (str, len)));
532 } 527 }
533 break; 528 break;
534 529
535 case DT_WCS_LEN: 530 case DT_WCS_LEN:
536 { 531 {
537 wchar_t *wstr = va_arg (ap, wchar_t *); 532 wchar_t *wstr = va_arg (ap, wchar_t *);
538 int wlen = va_arg (ap, int); 533 int wlen = va_arg (ap, int);
539 534
540 XPUSHs (taint (sv_2mortal (wcs2sv (wstr, wlen)))); 535 XPUSHs (sv_2mortal (wcs2sv (wstr, wlen)));
541 } 536 }
542 break; 537 break;
543 538
544 case DT_XEVENT: 539 case DT_XEVENT:
545 { 540 {
546 XEvent *xe = va_arg (ap, XEvent *); 541 XEvent *xe = va_arg (ap, XEvent *);
547 HV *hv = newHV (); 542 HV *hv = newHV ();
548 543
549# 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)
550# 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)
551# undef set 547# undef set
552 548
553 setiv (type, xe->type); 549 setiv (type, xe->type);
554 setiv (send_event, xe->xany.send_event); 550 setiv (send_event, xe->xany.send_event);
555 setiv (serial, xe->xany.serial); 551 setiv (serial, xe->xany.serial);
559 case KeyPress: 555 case KeyPress:
560 case KeyRelease: 556 case KeyRelease:
561 case ButtonPress: 557 case ButtonPress:
562 case ButtonRelease: 558 case ButtonRelease:
563 case MotionNotify: 559 case MotionNotify:
560 setuv (window, xe->xmotion.window);
561 setuv (root, xe->xmotion.root);
562 setuv (subwindow, xe->xmotion.subwindow);
564 setiv (time, xe->xmotion.time); 563 setuv (time, xe->xmotion.time);
565 setiv (x, xe->xmotion.x); 564 setiv (x, xe->xmotion.x);
566 setiv (y, xe->xmotion.y); 565 setiv (y, xe->xmotion.y);
567 setiv (row, xe->xmotion.y / term->fheight); 566 setiv (row, xe->xmotion.y / term->fheight);
568 setiv (col, xe->xmotion.x / term->fwidth); 567 setiv (col, xe->xmotion.x / term->fwidth);
569 setiv (x_root, xe->xmotion.x_root); 568 setiv (x_root, xe->xmotion.x_root);
570 setiv (y_root, xe->xmotion.y_root); 569 setiv (y_root, xe->xmotion.y_root);
571 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
572 break; 589 break;
573 }
574 590
591 case MapNotify:
592 case UnmapNotify:
593 case ConfigureNotify:
594 setuv (event, xe->xconfigure.event);
595 setuv (window, xe->xconfigure.window);
596
575 switch (xe->type) 597 switch (xe->type)
576 { 598 {
577 case KeyPress: 599 case ConfigureNotify:
578 case KeyRelease: 600 setiv (x, xe->xconfigure.x);
579 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);
580 break; 605 break;
581
582 case ButtonPress:
583 case ButtonRelease:
584 setiv (button, xe->xbutton.button);
585 break; 606 }
586 607
587 case MotionNotify:
588 setiv (is_hint, xe->xmotion.is_hint);
589 break; 608 break;
590 } 609 }
591 610
592 XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv))); 611 XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
593 } 612 }
634 else 653 else
635 event_consumed = false; 654 event_consumed = false;
636 655
637 // post-handling of some events 656 // post-handling of some events
638 if (htype == HOOK_REFRESH_BEGIN) 657 if (htype == HOOK_REFRESH_BEGIN)
639 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 }
640 else if (htype == HOOK_DESTROY) 664 else if (htype == HOOK_DESTROY)
641 { 665 {
642 clearSVptr ((SV *)term->perl.self); 666 clearSVptr ((SV *)term->perl.self);
643 SvREFCNT_dec ((SV *)term->perl.self); 667 SvREFCNT_dec ((SV *)term->perl.self);
644 } 668 }
782void 806void
783fatal (const char *msg) 807fatal (const char *msg)
784 CODE: 808 CODE:
785 rxvt_fatal ("%s", msg); 809 rxvt_fatal ("%s", msg);
786 810
787SV *
788untaint (SV *sv)
789 CODE:
790 RETVAL = newSVsv (sv);
791 SvTAINTED_off (RETVAL);
792 OUTPUT:
793 RETVAL
794
795void 811void
796_exit (int status) 812_exit (int status)
797
798bool
799safe ()
800 CODE:
801 RETVAL = !rxvt_tainted ();
802 OUTPUT:
803 RETVAL
804 813
805NV 814NV
806NOW () 815NOW ()
807 CODE: 816 CODE:
808 RETVAL = NOW; 817 RETVAL = NOW;
873 882
874 for (int i = 1; i < items; i++) 883 for (int i = 1; i < items; i++)
875 term->argv->push_back (strdup (SvPVbyte_nolen (ST (i)))); 884 term->argv->push_back (strdup (SvPVbyte_nolen (ST (i))));
876 885
877 AV *envv = (AV *)SvRV (ST (0)); 886 AV *envv = (AV *)SvRV (ST (0));
878 for (int i = av_len (envv) + 1; i--; ) 887 for (int i = AvFILL (envv) + 1; i--; )
879 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))));
880 889
881 term->envv->push_back (0); 890 term->envv->push_back (0);
882 891
883 bool success; 892 bool success;
1074 char *mbstr = rxvt_wcstombs (wstr); 1083 char *mbstr = rxvt_wcstombs (wstr);
1075 rxvt_pop_locale (); 1084 rxvt_pop_locale ();
1076 1085
1077 free (wstr); 1086 free (wstr);
1078 1087
1079 RETVAL = taint_if (newSVpv (mbstr, 0), str); 1088 RETVAL = newSVpv (mbstr, 0);
1080 free (mbstr); 1089 free (mbstr);
1081} 1090}
1082 OUTPUT: 1091 OUTPUT:
1083 RETVAL 1092 RETVAL
1084 1093
1091 1100
1092 rxvt_push_locale (THIS->locale); 1101 rxvt_push_locale (THIS->locale);
1093 wchar_t *wstr = rxvt_mbstowcs (data, len); 1102 wchar_t *wstr = rxvt_mbstowcs (data, len);
1094 rxvt_pop_locale (); 1103 rxvt_pop_locale ();
1095 1104
1096 RETVAL = taint_if (wcs2sv (wstr), octets); 1105 RETVAL = wcs2sv (wstr);
1097 free (wstr); 1106 free (wstr);
1098} 1107}
1099 OUTPUT: 1108 OUTPUT:
1100 RETVAL 1109 RETVAL
1101 1110
1253 wchar_t *wstr = new wchar_t [THIS->ncol]; 1262 wchar_t *wstr = new wchar_t [THIS->ncol];
1254 1263
1255 for (int col = 0; col < THIS->ncol; col++) 1264 for (int col = 0; col < THIS->ncol; col++)
1256 wstr [col] = l.t [col]; 1265 wstr [col] = l.t [col];
1257 1266
1258 XPUSHs (taint (sv_2mortal (wcs2sv (wstr, THIS->ncol)))); 1267 XPUSHs (sv_2mortal (wcs2sv (wstr, THIS->ncol)));
1259 1268
1260 delete [] wstr; 1269 delete [] wstr;
1261 } 1270 }
1262 1271
1263 if (new_text) 1272 if (new_text)
1306 { 1315 {
1307 if (!SvROK (new_rend) || SvTYPE (SvRV (new_rend)) != SVt_PVAV) 1316 if (!SvROK (new_rend) || SvTYPE (SvRV (new_rend)) != SVt_PVAV)
1308 croak ("new_rend must be arrayref"); 1317 croak ("new_rend must be arrayref");
1309 1318
1310 AV *av = (AV *)SvRV (new_rend); 1319 AV *av = (AV *)SvRV (new_rend);
1311 int len = min (av_len (av) + 1 - start_ofs, max_len); 1320 int len = min (AvFILL (av) + 1 - start_ofs, max_len);
1312 1321
1313 if (!IN_RANGE_INC (start_col, 0, THIS->ncol - len)) 1322 if (!IN_RANGE_INC (start_col, 0, THIS->ncol - len))
1314 croak ("new_rend array extends beyond horizontal margins"); 1323 croak ("new_rend array extends beyond horizontal margins");
1315 1324
1316 for (int col = start_col; col < start_col + len; col++) 1325 for (int col = start_col; col < start_col + len; col++)
1384 else 1393 else
1385 *r++ = *s; 1394 *r++ = *s;
1386 1395
1387 rxvt_pop_locale (); 1396 rxvt_pop_locale ();
1388 1397
1389 RETVAL = taint_if (wcs2sv (rstr, r - rstr), string); 1398 RETVAL = wcs2sv (rstr, r - rstr);
1390 1399
1391 delete [] rstr; 1400 delete [] rstr;
1392} 1401}
1393 OUTPUT: 1402 OUTPUT:
1394 RETVAL 1403 RETVAL
1420 else if (IS_COMPOSE (*s)) 1429 else if (IS_COMPOSE (*s))
1421 r += rxvt_composite.expand (*s, r); 1430 r += rxvt_composite.expand (*s, r);
1422 else 1431 else
1423 *r++ = *s; 1432 *r++ = *s;
1424 1433
1425 RETVAL = taint_if (wcs2sv (rstr, r - rstr), text); 1434 RETVAL = wcs2sv (rstr, r - rstr);
1426 1435
1427 delete [] rstr; 1436 delete [] rstr;
1428} 1437}
1429 OUTPUT: 1438 OUTPUT:
1430 RETVAL 1439 RETVAL
1452 1461
1453 if (!IN_RANGE_EXC (index, 0, NUM_RESOURCES)) 1462 if (!IN_RANGE_EXC (index, 0, NUM_RESOURCES))
1454 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);
1455 1464
1456 if (GIMME_V != G_VOID) 1465 if (GIMME_V != G_VOID)
1457 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);
1458 1467
1459 if (newval) 1468 if (newval)
1460 { 1469 {
1461 if (SvOK (newval)) 1470 if (SvOK (newval))
1462 { 1471 {
1469 } 1478 }
1470} 1479}
1471 1480
1472const char * 1481const char *
1473rxvt_term::x_resource (const char *name) 1482rxvt_term::x_resource (const char *name)
1474 CLEANUP:
1475 SvTAINTED_on (ST (0));
1476 1483
1477bool 1484bool
1478rxvt_term::option (U32 optval, int set = -1) 1485rxvt_term::option (U32 optval, int set = -1)
1479 CODE: 1486 CODE:
1480{ 1487{
1540 PUSHs (sv_2mortal (newSViv (rc.col))); 1547 PUSHs (sv_2mortal (newSViv (rc.col)));
1541 } 1548 }
1542 1549
1543 if (items == 3) 1550 if (items == 3)
1544 { 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);
1545 rc.row = clamp (SvIV (ST (1)), THIS->top_row, THIS->nrow - 1); 1562 clamp_it (rc.row, THIS->top_row, THIS->nrow - 1);
1546 rc.col = clamp (SvIV (ST (2)), 0, THIS->ncol - 1);
1547 1563
1548 if (ix) 1564 if (ix)
1549 THIS->want_refresh = 1; 1565 THIS->want_refresh = 1;
1550 } 1566 }
1551} 1567}
1574rxvt_term::selection (SV *newtext = 0) 1590rxvt_term::selection (SV *newtext = 0)
1575 PPCODE: 1591 PPCODE:
1576{ 1592{
1577 if (GIMME_V != G_VOID) 1593 if (GIMME_V != G_VOID)
1578 XPUSHs (THIS->selection.text 1594 XPUSHs (THIS->selection.text
1579 ? taint (sv_2mortal (wcs2sv (THIS->selection.text, THIS->selection.len))) 1595 ? sv_2mortal (wcs2sv (THIS->selection.text, THIS->selection.len))
1580 : &PL_sv_undef); 1596 : &PL_sv_undef);
1581 1597
1582 if (newtext) 1598 if (newtext)
1583 { 1599 {
1584 free (THIS->selection.text); 1600 free (THIS->selection.text);
1710 RETVAL = THIS; 1726 RETVAL = THIS;
1711 OUTPUT: 1727 OUTPUT:
1712 RETVAL 1728 RETVAL
1713 1729
1714timer * 1730timer *
1731timer::after (NV delay)
1732 CODE:
1733 THIS->start (NOW + delay);
1734 OUTPUT:
1735 RETVAL
1736
1737timer *
1715timer::stop () 1738timer::stop ()
1716 CODE: 1739 CODE:
1717 THIS->stop (); 1740 THIS->stop ();
1718 RETVAL = THIS; 1741 RETVAL = THIS;
1719 OUTPUT: 1742 OUTPUT:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines