netsurf/riscos/message.c
Daniel Silverstone 6807b4208a Remove the netsurf/ from the include paths and rationalise use of <> vs "" in includes
NetSurf includes are now done with ""s and other system includes with <>s as C intended.
The scandeps tool has been updated to only look for ""ed includes, and to verify that the
files exist in the tree before adding them to the dependency lines. The depend rule has
therefore been augmented to make sure the autogenerated files are built before it is run.

This is untested under self-hosted RISC OS builds. All else tested and works.


svn path=/trunk/netsurf/; revision=3307
2007-05-30 22:39:54 +00:00

230 lines
5.7 KiB
C

/*
* This file is part of NetSurf, http://netsurf-browser.org/
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
* Copyright 2006 Richard Wilson <info@tinct.net>
*/
/** \file
* Automated RISC OS message routing (implementation).
*/
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include "oslib/os.h"
#include "oslib/wimp.h"
#include "riscos/message.h"
#include "utils/log.h"
#include "utils/utils.h"
struct active_message {
unsigned int message_code;
int id;
void (*callback)(wimp_message *message);
struct active_message *next;
struct active_message *previous;
};
struct active_message *current_messages = NULL;
static struct active_message *ro_message_add(unsigned int message_code,
void (*callback)(wimp_message *message));
static void ro_message_free(int ref);
/**
* Sends a message and registers a return route for a bounce.
*
* \param event the message event type
* \param message the message to register a route back for
* \param task the task to send a message to, or 0 for broadcast
* \param callback the code to call on a bounce
* \return true on success, false otherwise
*/
bool ro_message_send_message(wimp_event_no event, wimp_message *message,
wimp_t task, void (*callback)(wimp_message *message)) {
os_error *error;
assert(message);
/* send a message */
error = xwimp_send_message(event, message, task);
if (error) {
LOG(("xwimp_send_message: 0x%x: %s",
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
return false;
}
/* register the default bounce handler */
if (callback) {
assert(event == wimp_USER_MESSAGE_RECORDED);
return ro_message_register_handler(message, message->action,
callback);
}
return true;
}
/**
* Sends a message and registers a return route for a bounce.
*
* \param event the message event type
* \param message the message to register a route back for
* \param to_w the window to send the message to
* \param to_i the icon
* \param callback the code to call on a bounce
* \param to_t receives the task handle of the window's creator
* \return true on success, false otherwise
*/
bool ro_message_send_message_to_window(wimp_event_no event, wimp_message *message,
wimp_w to_w, wimp_i to_i, void (*callback)(wimp_message *message),
wimp_t *to_t) {
os_error *error;
assert(message);
/* send a message */
error = xwimp_send_message_to_window(event, message, to_w, to_i, to_t);
if (error) {
LOG(("xwimp_send_message_to_window: 0x%x: %s",
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
return false;
}
/* register the default bounce handler */
if (callback) {
assert(event == wimp_USER_MESSAGE_RECORDED);
return ro_message_register_handler(message, message->action,
callback);
}
return true;
}
/**
* Registers a return route for a message.
*
* This function must be called after wimp_send_message so that a
* valid value is present in the my_ref field.
*
* \param message the message to register a route back for
* \param message_code the message action code to route
* \param callback the code to call for a matched action
* \return true on success, false on memory exhaustion
*/
bool ro_message_register_handler(wimp_message *message,
unsigned int message_code,
void (*callback)(wimp_message *message)) {
struct active_message *add;
assert(message);
assert(callback);
add = ro_message_add(message_code, callback);
if (add)
add->id = message->my_ref;
return (add != NULL);
}
/**
* Registers a route for a message code.
*
* \param message_code the message action code to route
* \param callback the code to call for a matched action
* \return true on success, false on memory exhaustion
*/
bool ro_message_register_route(unsigned int message_code,
void (*callback)(wimp_message *message)) {
assert(callback);
return (ro_message_add(message_code, callback) != NULL);
}
struct active_message *ro_message_add(unsigned int message_code,
void (*callback)(wimp_message *message)) {
struct active_message *add;
assert(callback);
add = (struct active_message *)malloc(sizeof(*add));
if (!add)
return NULL;
add->message_code = message_code;
add->id = 0;
add->callback = callback;
add->next = current_messages;
add->previous = NULL;
current_messages = add;
return add;
}
/**
* Attempts to route a message.
*
* \param message the message to attempt to route
* \return true if message was routed, false otherwise
*/
bool ro_message_handle_message(wimp_event_no event, wimp_message *message) {
struct active_message *test;
bool handled = false;
int ref;
assert(message);
if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) {
/* handle message acknowledgement */
ref = message->my_ref;
if (ref == 0)
return false;
/* handle the message */
for (test = current_messages; test; test = test->next) {
if ((ref == test->id) &&
(message->action == test->message_code)) {
handled = true;
if (test->callback)
test->callback(message);
break;
}
}
/* remove all handlers for this id */
ro_message_free(ref);
return handled;
} else {
/* handle simple routing */
for (test = current_messages; test; test = test->next) {
if ((test->id == 0) &&
(message->action == test->message_code)) {
test->callback(message);
return true;
}
}
}
return false;
}
void ro_message_free(int ref) {
struct active_message *test;
struct active_message *next = current_messages;
while ((test = next)) {
next = test->next;
if (ref == test->id) {
if (test->previous)
test->previous->next = test->next;
if (test->next)
test->next->previous = test->previous;
if (current_messages == test)
current_messages = test->next;
free(test);
}
}
}