Add libwx-perl
[pkg-perl] / deb-src / libwx-perl / libwx-perl-0.96 / cpp / e_cback.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        cpp/e_cback.cpp
3 // Purpose:     implementation for e_cback.h
4 // Author:      Mattia Barbon
5 // Modified by:
6 // Created:     29/10/2000
7 // RCS-ID:      $Id: e_cback.cpp 2454 2008-08-31 11:12:47Z mbarbon $
8 // Copyright:   (c) 2000-2002, 2004-2008 Mattia Barbon
9 // Licence:     This program is free software; you can redistribute it and/or
10 //              modify it under the same terms as Perl itself
11 /////////////////////////////////////////////////////////////////////////////
12
13 wxPliEventCallback::wxPliEventCallback( SV* method, SV* self ) 
14 {
15     dTHX;
16     m_method = method;
17     SvREFCNT_inc( m_method );
18     m_self = self;
19     SvREFCNT_inc( m_self );
20     m_is_method = !SvROK( m_method ) || !SvRV( m_method );
21 }
22
23 wxPliEventCallback::~wxPliEventCallback() 
24 {
25     dTHX;
26     SvREFCNT_dec( m_method );
27     SvREFCNT_dec( m_self );
28 }
29
30 class wxPliGuard
31 {
32 public:
33     wxPliGuard()
34     {
35         m_sv = NULL;
36     }
37
38     ~wxPliGuard()
39     {
40         if( m_sv )
41         {
42             dTHX;
43
44             wxPli_thread_sv_unregister( aTHX_ wxPli_get_class( aTHX_ m_sv ),
45                                         (void*)SvIV( m_sv ), m_sv );
46             sv_setiv( m_sv, 0 );
47         }
48     }
49
50     void SetSV( SV* sv ) { m_sv = sv; }
51 private:
52     SV* m_sv;
53 };
54
55 void wxPliEventCallback::Handler( wxEvent& event ) 
56 {
57     wxPliEventCallback* This = (wxPliEventCallback*) event.m_callbackUserData;
58
59     dTHX;
60     dSP;
61
62     ENTER;
63     SAVETMPS;
64
65     {
66         // similar to wxPli_object_2_sv
67         wxPliGuard guard;
68         SV* e = 0;
69         SV* rv = 0;
70         wxClassInfo *ci = event.GetClassInfo();
71         const wxChar* classname = ci->GetClassName();
72
73 #if wxUSE_UNICODE
74         if( wcsncmp( classname, wxT("wxPl"), 4 ) == 0 ) 
75 #else
76         if( strnEQ( classname, "wxPl", 4 ) ) 
77 #endif
78         {
79             wxPliClassInfo* cci = (wxPliClassInfo*)ci;
80             wxPliSelfRef* sr = cci->m_func( &event );
81         
82             if( sr )
83             {
84                 // this needs to have the refcount incremented, otherwise
85                 // the refcount will be decremented one time too much when
86                 // exiting from the handler
87                 e = sv_2mortal( newRV_inc( SvRV( sr->m_self ) ) );
88             }
89         }
90
91         if( !e )
92         {
93             char buffer[WXPL_BUF_SIZE];
94             const char* CLASS = wxPli_cpp_class_2_perl( classname, buffer );
95
96             e = sv_newmortal();
97             sv_setref_pv( e, CHAR_P CLASS, &event );
98             rv = SvRV( e );
99             // corner case: prevent destruction if referrer is
100             // destroyed
101             SvREFCNT_inc( rv );
102             sv_2mortal( rv );
103             guard.SetSV( rv );
104             wxPli_thread_sv_register( aTHX_ CLASS, &event, e );
105         }
106
107         PUSHMARK( SP );
108         XPUSHs( This->m_self );
109         XPUSHs( e );
110         PUTBACK;
111
112         if( This->m_is_method )
113         {
114             call_method( SvPV_nolen( This->m_method ), G_EVAL|G_VOID|G_DISCARD );
115         }
116         else
117         {
118             call_sv( This->m_method, G_EVAL|G_VOID|G_DISCARD );
119         }
120
121         SPAGAIN;
122     }
123
124     if( SvTRUE( ERRSV ) )
125     {
126         croak( Nullch );
127     }
128
129     PUTBACK;
130     FREETMPS;
131     LEAVE;
132 }
133
134 // Local variables: //
135 // mode: c++ //
136 // End: //