home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / lang / cplus / 13369 < prev    next >
Encoding:
Text File  |  1992-09-08  |  4.6 KB  |  171 lines

  1. Path: sparky!uunet!mcsun!uknet!glasgow!edrc!a_mahmoo
  2. From: a_mahmoo@edrc.ac.uk (Arshad Mahmood)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Callbacks - C++ needs an extension?
  5. Message-ID: <1992Sep7.173259.7012@edrc.ac.uk>
  6. Date: 7 Sep 92 17:32:59 GMT
  7. References: <DAVIDM.92Aug31105639@consilium.com> <la83j0INN839@appserv.Eng.Sun.COM>
  8. Sender: news@edrc.ac.uk (News System)
  9. Organization: Engineering Design Research Centre
  10. Lines: 159
  11.  
  12. A slightly different approach as covered in D. Young's book is to rely on a
  13. global callback (and event handler), which supplies the implicit this
  14. pointer to the method (accellarators are probably still best handled as
  15. per David's solution). The code below (not taken from Young, I wrote this
  16. before the book was published) is an example of how this can be
  17. done (in this case your classes have to be subclasses of XCC to make use of
  18. this facility, no doubt other's can think of other ways to go about it
  19. (any ideas on how to implement this in a much nicer way are welcome, the
  20. class LIST and LIST_Iterator are NOT supplied get in touch if you want to 
  21. make use of it, and I will supply you the rest of code and an example).
  22.  
  23. /*
  24.   File: XCC.h
  25.   Description:
  26.   My rather daft way of implementing callbacks for C++.
  27. */
  28.  
  29. #ifndef _XCC_H
  30. #define _XCC_H
  31.  
  32. #include <X11/Intrinsic.h>
  33. #include "list.h"
  34.  
  35. class XCC;
  36.  
  37. typedef void (XCC::*Callback)(Widget, void*, void*);
  38. typedef void (XCC::*EventHandler)(Widget, void*, XEvent*);
  39.  
  40. class XCC {
  41.  public:
  42.   XCC();
  43.   ~XCC();
  44.  
  45.   void AddCCCallback(Widget w, char* name, Callback cb, void* client_data);
  46.   void AddCCEventHandler(Widget w, EventMask, Boolean, EventHandler, void*);
  47.  
  48.  private: /* if you're using gnu the next two functions have to be public */
  49.   static void theCallback(Widget, void*, void*);
  50.   static void theHandler(Widget, void*, XEvent*);
  51.  
  52.   LIST client_data_list;
  53. };
  54.  
  55. #define AddCallback(w,name,cb,cdata) AddCCCallback(w,name, (Callback)&cb,cdata)
  56.  
  57. #define AddEventHandler(w,mask,nonmaskable,handler,cdata) \
  58.            AddCCEventHandler(w,mask,nonmaskable,(EventHandler)&handler, cdata)
  59.  
  60. #endif _XCC_H
  61. -----------------------------------------
  62. /*
  63.   File: XCC.C
  64.  
  65. */
  66.  
  67. #include "XCC.h"
  68. #include "list_it.h"
  69.  
  70. /*
  71.   XCCStruct - This structure is passed as client data to the event handlers
  72.           and callbacks, it passes the implicit this pointer "me" so
  73.           so that member functions may be passed as callbacks and
  74.           event handlers.
  75. */
  76.  
  77. typedef struct
  78. {
  79.   XCC*   me;
  80.   EventHandler handler;
  81.   Callback   callback;
  82.   void*      client_data;
  83. } XCCStruct;
  84.  
  85. XCC::XCC()
  86. {
  87. }
  88.  
  89.  XCC::~XCC()
  90. {
  91.   LIST_Iterator it(client_data_list);
  92.   XCCStruct* x;
  93.  
  94.   foreach(it,XCCStruct*,x) delete x;
  95. }
  96.  
  97. /*
  98.   AddCCCallback - like the toolkit function XtAddcallback this one 
  99.   adds a particular member function as a callback. In order to use
  100.   C++, I have routed all callbacks through one central callback
  101.   (XCC::theCallback), the client data for this tells it what to
  102.   do above and beyond that.
  103. */
  104.  
  105. void XCC::AddCCCallback(Widget w, char* name, Callback cb, 
  106.                 void* client_data)
  107. {
  108.   XCCStruct* x = new XCCStruct;
  109.  
  110.   x->callback = cb;
  111.   x->client_data = client_data;
  112.   x->me = (XCC *)this;
  113.  
  114.   XtAddCallback(w, name, (XtCallbackProc)XCC::theCallback, (XtPointer)x);
  115.   client_data_list.InsertAtEnd((void *)x);
  116. }
  117.  
  118. /*
  119.   AddCCEventHandler - Register a C++ event handler, as with the callbacks
  120.                       all events pass through a central handler
  121.               (theHandler)
  122. */
  123.  
  124. void XCC::AddCCEventHandler(Widget w, EventMask mask, Boolean nonmaskable,
  125.                 EventHandler handler, void* client_data)
  126. {
  127.   XCCStruct* x = new XCCStruct;
  128.  
  129.   x->handler = handler;
  130.   x->client_data = client_data;
  131.   x->me = (XCC *)this;
  132.  
  133.   XtAddEventHandler(w, mask, nonmaskable, (XtEventHandler)XCC::theHandler, 
  134.             (XtPointer)x);
  135.   client_data_list.InsertAtEnd((void *)x);
  136. }
  137.  
  138. /*
  139.  theCallback - This is the central callback for all callbacks
  140.                 registered as members of classes. It's a static member
  141.         of the class.
  142. */
  143.   
  144. void XCC::theCallback(Widget w, void* client_data, void* call_data)
  145. {
  146.   XCCStruct* cb_struct = (XCCStruct *)client_data;
  147.   XCC* mclass = cb_struct->me;
  148.   
  149.   (mclass->*(cb_struct->callback))(w, cb_struct->client_data, call_data);
  150. }
  151.  
  152. /*
  153.   theHandler - This is the central handler through which all C++ based
  154.                Event Handlers work.
  155. */
  156.  
  157. void XCC::theHandler(Widget w, void* client_data, XEvent* event)
  158. {
  159.   XCCStruct* cb_struct = (XCCStruct *)client_data;
  160.   XCC* mclass = cb_struct->me;
  161.  
  162.   (mclass->*(cb_struct->handler))(w, cb_struct->client_data, event);
  163.  
  164. ------------------------ end of XCC.C --
  165. Regards,
  166. A. Mahmood
  167. Systems Manager
  168. EDRC
  169. e-mail: a_mahmoo@uk.ac.edrc
  170.