home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / toollib_2 / !ToolLib / c / nev_messag < prev    next >
Text File  |  1996-06-13  |  6KB  |  246 lines

  1. /*** nev_message.c ***/
  2. /* Handle Wimp messages.
  3.  * By Paul Field
  4.  */
  5.  
  6. #include "nev_message.h"
  7.  
  8. #include <assert.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11.  
  12. #include "allocate.h"
  13. #include "list.h"
  14.  
  15. #include "nev_support.h"
  16.  
  17.  
  18. typedef struct message_handler_info
  19.  { unsigned               message_num;
  20.    nevent_message_handler handler;
  21.    void*                  handle;
  22.  }
  23. message_handler_info;
  24.  
  25.  
  26. static list* handler_list;
  27.  
  28.  
  29. #ifndef NDEBUG
  30. #include "set.h"
  31.  
  32. static bool initialised = FALSE;
  33. static const wimp_message_list* all_messages;
  34.  
  35. static set* message_set;
  36.  
  37.  
  38. static int compare_messages(const void* vnum1, const void* vnum2)
  39.  { bits num1 = *(const int *)vnum1;
  40.    bits num2 = *(const int *)vnum2;
  41.  
  42.    if (num1 < num2)
  43.     { return -1;
  44.     }
  45.    if (num1 == num2)
  46.     { return 0;
  47.     }
  48.    return 1;
  49.  }
  50.  
  51.  
  52.  
  53.  
  54. static void output_message_set(void)
  55.  { set_ptr ptr;
  56.  
  57.    fputs
  58.     ( "--------------------------\n"
  59.       "Messages for which handlers were registered:\n"
  60.       " {\n",
  61.       stderr
  62.     );
  63.  
  64.    for (ptr = set_ptr_first(message_set); !set_ptr_past_the_end(ptr); set_ptr_inc(&ptr))
  65.     { bits message_num;
  66.  
  67.       message_num = *(bits *)set_ptr_element(ptr);
  68.       if (message_num != nevent_ALL_MESSAGES && message_num != 0)
  69.        { fprintf(stderr,"   0x%x,\n", message_num);
  70.        }
  71.     }
  72.  
  73.    fputs("   0\n };\n", stderr);
  74.  }
  75.  
  76.  
  77.  
  78.  
  79. static bool message_can_arrive(int message_no)
  80.  { if (all_messages == NULL)
  81.     { /* NULL means "no messages" except that message_QUIT is always returned */
  82.       return (message_no == message_QUIT);
  83.     }
  84.    else
  85.     { /* If the list only contains 0 then all messages are delivered */
  86.       if (all_messages->messages[0] == 0)
  87.        { return TRUE;
  88.        }
  89.       else
  90.        { /* Messages are explicitly listed - so look for our messages */
  91.          unsigned i     = 0;
  92.          bool     end   = FALSE;
  93.          bool     found = FALSE;
  94.  
  95.          do
  96.           { end   = (all_messages->messages[i] == 0);
  97.             found = (all_messages->messages[i] == message_no);
  98.             i++;
  99.           }
  100.          while(!end && !found);
  101.  
  102.          return found;
  103.        }
  104.     }
  105.  }
  106.  
  107.  
  108.  
  109.  
  110. static void check_message_is_delivered(int message_no)
  111.  { if (!message_can_arrive(message_no))
  112.     { fprintf
  113.        ( stderr,
  114.          "Message %x was not passed to nev_message_initialise() but a handler has been registered for it\n",
  115.           message_no
  116.        );
  117.     }
  118.  }
  119. #else
  120. /* Define 'null' function so no code is included when the production version is compiled */
  121. #define check_message_is_delivered(m)
  122.  
  123. #endif
  124.  
  125.  
  126.  
  127.  
  128. static bool nevent_message_dispatch(wimp_event_no event_num, wimp_block* poll_block, toolbox_block* id_block)
  129.  { NOT_USED(id_block);
  130.  
  131.    if (event_num == wimp_USER_MESSAGE || event_num == wimp_USER_MESSAGE_RECORDED)
  132.     { list_ptr ptr;
  133.  
  134.       assert(initialised);
  135.       assert(poll_block != NULL);
  136.  
  137.       for (ptr = list_ptr_head(handler_list); !list_ptr_past_the_end(ptr); list_ptr_inc(&ptr))
  138.        { const message_handler_info* handler_info;
  139.  
  140.          handler_info = list_ptr_element(ptr);
  141.          if
  142.           (handler_info->message_num == nevent_ALL_MESSAGES ||
  143.            handler_info->message_num == poll_block->message.action
  144.           )
  145.           { if (handler_info->handler(&poll_block->message, handler_info->handle))
  146.              { return TRUE;
  147.              }
  148.           }
  149.        }
  150.       return TRUE;
  151.     }
  152.    return FALSE;
  153.  }
  154.  
  155.  
  156.  
  157.  
  158. void nevent_message_register_handler(bits message_num, nevent_message_handler handler, void* handle)
  159.  { message_handler_info* handler_info;
  160.  
  161.    assert(initialised);
  162.    assert(handler != NULL);
  163.    check_message_is_delivered(message_num);
  164. #ifndef NDEBUG
  165.    set_insert(message_set, &message_num);
  166. #endif
  167.  
  168.    handler_info = list_alloc_element(sizeof(message_handler_info));
  169.    handler_info->message_num = message_num;
  170.    handler_info->handler     = handler;
  171.    handler_info->handle      = handle;
  172.    list_cons(handler_list, handler_info);
  173.  }
  174.  
  175.  
  176.  
  177.  
  178. void nevent_message_deregister_handler(bits message_num, nevent_message_handler handler, void* handle)
  179.  { message_handler_info* handler_info;
  180.  
  181.    assert(initialised);
  182.    assert(handler != NULL);
  183.  
  184. #ifndef NDEBUG
  185.    if (list_is_empty(handler_list))
  186.     { fprintf
  187.        ( stderr,
  188.          "Error: Unable to deregister nevent_wimp_message_handler %p for message %x with handle %p\n",
  189.          handler,
  190.          message_num,
  191.          handle
  192.        );
  193.       return;
  194.     }
  195. #endif
  196.  
  197.    handler_info = list_remove_head(handler_list);
  198.    if
  199.     ( handler_info->message_num == message_num &&
  200.       handler_info->handler     == handler     &&
  201.       handler_info->handle      == handle
  202.     )
  203.     { list_free_element(handler_info);
  204.     }
  205.    else
  206.     { nevent_message_deregister_handler(message_num, handler, handle);
  207.       list_cons(handler_list, handler_info);
  208.     }
  209.  }
  210.  
  211.  
  212.  
  213.  
  214. #ifndef NDEBUG
  215. /* Clear up memory used - only needed in debug code, because OS does it automatically
  216.  * but tidying up stop memory leak checkers (e.g. MemCheck) from listing all the
  217.  * memory we used
  218.  */
  219. static void tidy_up(void)
  220.  { list_destroy(handler_list);
  221.    set_destroy(message_set);
  222.  }
  223. #endif
  224.  
  225.  
  226.  
  227.  
  228. void nevent_message_initialise(const wimp_message_list* messages)
  229.  { assert(!initialised);
  230.  
  231.    handler_list = list_create();
  232.    nevent_support_register_dispatcher(nevent_message_dispatch);
  233.  
  234. #ifndef NDEBUG
  235.    initialised = TRUE;
  236.    all_messages = messages;
  237.    message_set = set_create(compare_messages, NULL, sizeof(bits));
  238.  
  239.    /* N.B. atexit handlers called in reverse order of registration */
  240.    atexit(tidy_up);
  241.    atexit(output_message_set);
  242. #else
  243.    NOT_USED(messages);
  244. #endif
  245.  }
  246.