GtkClosures.mod 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. IMPLEMENTATION MODULE GtkClosures ;
  2. (*
  3. Each connection gets a Context holding the handler, the user payload
  4. and an optional destroy procedure. Two trampolines (2-argument and
  5. 3-argument) recover the Context from their pointer parameter and
  6. forward the call. DestroyCtx is registered as the GClosure destroy
  7. notify, so it runs on both explicit disconnect and object finalize.
  8. Trampoline parameters are typed pointers (ContextPtr), so the C
  9. gpointer is received without a CAST on the hot path.
  10. *)
  11. FROM SYSTEM IMPORT ADDRESS, CAST, ADR;
  12. FROM Storage IMPORT ALLOCATE, DEALLOCATE;
  13. FROM GObject IMPORT g_signal_connect_data, GConnectDefault;
  14. TYPE
  15. Context = RECORD
  16. user: ADDRESS;
  17. destroy: DestroyProc;
  18. h2: Handler2;
  19. h3: Handler3;
  20. END;
  21. ContextPtr = POINTER TO Context;
  22. PROCEDURE Tramp2 (instance: ADDRESS; ctx: ContextPtr);
  23. BEGIN
  24. ctx^.h2(instance, ctx^.user)
  25. END Tramp2;
  26. PROCEDURE Tramp3 (instance: ADDRESS; param: ADDRESS; ctx: ContextPtr);
  27. BEGIN
  28. ctx^.h3(instance, param, ctx^.user)
  29. END Tramp3;
  30. PROCEDURE DestroyCtx (ctx: ContextPtr; closure: ADDRESS);
  31. BEGIN
  32. IF ctx # NIL THEN
  33. IF ctx^.destroy # NIL THEN
  34. ctx^.destroy(ctx^.user)
  35. END;
  36. DISPOSE(ctx)
  37. END
  38. END DestroyCtx;
  39. PROCEDURE NewCtx () : ContextPtr;
  40. VAR
  41. ctx: ContextPtr;
  42. BEGIN
  43. NEW(ctx);
  44. ctx^.user := NIL;
  45. ctx^.destroy := NIL;
  46. ctx^.h2 := NIL;
  47. ctx^.h3 := NIL;
  48. RETURN ctx
  49. END NewCtx;
  50. PROCEDURE RawConnect (instance: ADDRESS; signal: ARRAY OF CHAR;
  51. ctx: ContextPtr; tramp: ADDRESS) : [ LONGCARD ];
  52. BEGIN
  53. RETURN g_signal_connect_data(instance, signal, tramp, CAST(ADDRESS, ctx),
  54. ADR(DestroyCtx), GConnectDefault)
  55. END RawConnect;
  56. PROCEDURE Connect2 (instance: ADDRESS; signal: ARRAY OF CHAR;
  57. handler: Handler2; user: ADDRESS) : [ LONGCARD ];
  58. VAR
  59. ctx: ContextPtr;
  60. BEGIN
  61. ctx := NewCtx();
  62. ctx^.h2 := handler;
  63. ctx^.user := user;
  64. RETURN RawConnect(instance, signal, ctx, ADR(Tramp2))
  65. END Connect2;
  66. PROCEDURE Connect3 (instance: ADDRESS; signal: ARRAY OF CHAR;
  67. handler: Handler3; user: ADDRESS) : [ LONGCARD ];
  68. VAR
  69. ctx: ContextPtr;
  70. BEGIN
  71. ctx := NewCtx();
  72. ctx^.h3 := handler;
  73. ctx^.user := user;
  74. RETURN RawConnect(instance, signal, ctx, ADR(Tramp3))
  75. END Connect3;
  76. PROCEDURE Connect2Owned (instance: ADDRESS; signal: ARRAY OF CHAR;
  77. handler: Handler2; user: ADDRESS;
  78. destroy: DestroyProc) : [ LONGCARD ];
  79. VAR
  80. ctx: ContextPtr;
  81. BEGIN
  82. ctx := NewCtx();
  83. ctx^.h2 := handler;
  84. ctx^.user := user;
  85. ctx^.destroy := destroy;
  86. RETURN RawConnect(instance, signal, ctx, ADR(Tramp2))
  87. END Connect2Owned;
  88. PROCEDURE Connect3Owned (instance: ADDRESS; signal: ARRAY OF CHAR;
  89. handler: Handler3; user: ADDRESS;
  90. destroy: DestroyProc) : [ LONGCARD ];
  91. VAR
  92. ctx: ContextPtr;
  93. BEGIN
  94. ctx := NewCtx();
  95. ctx^.h3 := handler;
  96. ctx^.user := user;
  97. ctx^.destroy := destroy;
  98. RETURN RawConnect(instance, signal, ctx, ADR(Tramp3))
  99. END Connect3Owned;
  100. END GtkClosures.