netsurf/riscos/plugin.c
John Mark Bell 1e6e665e35 [project @ 2003-08-26 00:50:51 by jmb]
Make plugins work on WIMP versions below 4.00

svn path=/import/netsurf/; revision=250
2003-08-26 00:50:51 +00:00

1550 lines
55 KiB
C

/*
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
* Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
*/
/*
* TODO:
* - Reshaping plugin (ie. call plugin_reshape_instance from somewhere)
* [Plugin_Reshape (&4d544), Plugin_Reshape_Request (&4d545)]
* - Finish off stream protocol implementation
* [Plugin_Stream_Write (&4d54a), Plugin_Stream_Written (&4d54b)]
* - Parse and act upon the rest of the Plugin_Opening flags
* - Handle death of Plugin Task
* - Implement remaining messages [Plugin_URL_Access, Plugin_Focus,
* Plugin_Notify, Plugin_Busy, Plugin_Action, Plugin_Abort,
* Plugin_Inform(ed)?]
* - Handle standalone objects
*/
#define NDEBUG
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "netsurf/content/content.h"
#include "netsurf/desktop/browser.h"
#include "netsurf/desktop/gui.h"
#include "netsurf/render/html.h"
#include "netsurf/render/box.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/plugin.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/utils.h"
#include "oslib/mimemap.h"
#include "oslib/os.h"
#include "oslib/osfile.h"
#include "oslib/osfind.h"
#include "oslib/osgbpb.h"
#include "oslib/plugin.h"
#include "oslib/wimp.h"
/* parameters file creation */
void plugin_write_parameters_file(struct object_params *params);
void plugin_populate_pdata(int rsize, byte *pdata);
/* stream handling */
void plugin_create_stream(struct browser_window *bw,
struct object_params *params, struct content *c);
void plugin_write_stream_as_file(struct browser_window *bw,
struct object_params *params,
struct content *c);
void plugin_destroy_stream(struct browser_window *bw,
struct object_params *params, struct content *c);
/* linked list handling */
struct plugin_message *plugin_add_message_to_linked_list(plugin_b browser,
plugin_p plugin,
wimp_message *m,
struct plugin_message *reply);
void plugin_remove_message_from_linked_list(struct plugin_message* m);
struct plugin_message *plugin_get_message_from_linked_list(int ref);
void plugin_add_instance_to_list(struct content *c,
struct browser_window *bw,
struct content *page, struct box *box,
struct object_params *params, void **state);
void plugin_remove_instance_from_list(struct object_params *params);
struct plugin_list *plugin_get_instance_from_list(plugin_b browser,
plugin_p plugin);
/* message handling */
void plugin_open(wimp_message *message);
void plugin_opening(wimp_message *message);
void plugin_close(wimp_message *message);
void plugin_closed(wimp_message *message);
void plugin_reshape_request(wimp_message *message);
void plugin_stream_new(wimp_message *message);
void plugin_status(wimp_message *message);
char *plugin_get_string_value(os_string_value string, char *msg);
/* others */
void plugin_create_sysvar(const char *mime_type, char *sysvar);
int plugin_process_opening(struct object_params *params,
struct plugin_message *message);
/*-------------------------------------------------------------------------*/
/* Linked List pointers */
/*-------------------------------------------------------------------------*/
static struct plugin_message pm = {0, 0, 0, 0, 0, &pm, &pm};
static struct plugin_message *pmlist = &pm;
static struct plugin_list pl = {0, 0, 0, 0, 0, 0, &pl, &pl};
static struct plugin_list *plist = &pl;
/*-------------------------------------------------------------------------*/
/* Externally visible functions */
/*-------------------------------------------------------------------------*/
/**
* plugin_create
* initialises plugin system in readiness for receiving object data
*/
void plugin_create(struct content *c)
{
c->data.plugin.data = xcalloc(0, 1);
c->data.plugin.length = 0;
/* we can't create the plugin here, because this is only called
* once, even if the object appears several times */
}
/**
* plugin_add_instance
*
* The content has been added to a page somewhere: launch the plugin.
* This may be called anytime after plugin_create any number of times.
* Each must launch a new plugin.
*
* bw is the window which the plugin is in
* page, box, params are 0 if the object is standalone
* state may be use to store a pointer to state data
*/
void plugin_add_instance(struct content *c, struct browser_window *bw,
struct content *page, struct box *box,
struct object_params *params, void **state)
{
char sysvar[40];
char *varval;
int size;
os_var_type var;
os_error *e;
// wimp_message *m = xcalloc(256, sizeof(char));
wimp_message m;
plugin_message_open *pmo;
os_box b;
struct plugin_message *npm = xcalloc(1, sizeof(*npm));
struct plugin_message *temp;
struct plugin_list *npl = xcalloc(1, sizeof(*npl));
int offset;
unsigned char *pchar = (unsigned char*)&m.data;
int flags = 0;
if (params == 0) {
fprintf(stderr,
"Cannot handle standalone objects at this time");
gui_window_set_status(bw->window,
"Plugin Error: Cannot handle standalone objects at this time");
// xfree(m);
xfree(npm);
xfree(npl);
return;
}
/* write parameters file */
plugin_write_parameters_file(params);
/* Get contents of Alias$@PlugInType_xxx system variable. */
plugin_create_sysvar(c->mime_type, sysvar);
xos_read_var_val_size(sysvar, 0, 0, &size, NULL, &var);
if(var != 3)
size = ~(size);
varval = xcalloc((unsigned int)size, sizeof(char));
xos_read_var_val(sysvar, varval, size, 0, var, NULL, NULL, NULL);
LOG(("%s: %s", sysvar, varval));
/* Broadcast Message_PlugIn_Open (&4D540) and listen for response
* Message_PlugIn_Opening (&4D541). If no response, try to launch
* plugin by Wimp_StartTask(sysvar). Then re-broadcast Message_PlugIn_Open
* and listen for response. If there is still no response, give up.
* NB: For the bounding box in Message_PlugIn_Open, we choose arbitrary
* values outside the area displayed. This is corrected when
* plugin_redraw is called.
*/
/* Initialise bounding box */
b.x0 = 100;
b.x1 = 1000;
b.y0 = 100;
b.y1 = 1000;
/* populate plugin_message_open struct */
pmo = (plugin_message_open*)&m.data;
pmo->flags = 0;
pmo->reserved = 0;
pmo->browser = (plugin_b)params->browser;
pmo->parent_window = bw->window->data.browser.window;
pmo->bbox = b;
xmimemaptranslate_mime_type_to_filetype(c->mime_type, &pmo->file_type);
offset = 56;
pmo->filename.offset = offset;
strncpy((char*)&pchar[offset], params->filename, (unsigned int)236-offset);
offset = offset + strlen(params->filename) + 1;
if (offset > 235) {
LOG(("filename too long"));
// xfree(m);
xfree(npm);
xfree(npl);
xfree(varval);
return;
}
m.size = ((20 + offset + 3) / 4) * 4;
m.your_ref = 0;
m.action = message_PLUG_IN_OPEN;
/* add message to list */
temp = plugin_add_message_to_linked_list((plugin_b)params->browser, (plugin_p)0, &m, (struct plugin_message*)0);
LOG(("Sending Message: &4D540"));
LOG(("Message Size: %d", m.size));
e = xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m, wimp_BROADCAST);
if(e) LOG(("Error: %s", e->errmess));
/* wait for wimp poll */
while(temp->poll == 0)
gui_poll();
if(temp->plugin != 0 && temp->reply != 0) {
/* ok, we got a reply */
LOG(("Reply to message %p: %p", temp, temp->reply));
flags = plugin_process_opening(params, temp);
plugin_remove_message_from_linked_list(temp->reply);
plugin_remove_message_from_linked_list(temp);
xfree(varval);
// xfree(m);
xfree(npm);
xfree(npl);
} else {
/* no reply so issue Wimp_StartTask(varval) */
LOG(("No reply to message %p", temp));
plugin_remove_message_from_linked_list(temp);
LOG(("Starting task: %s", varval));
e = xwimp_start_task((char const*)varval, NULL);
if(e) LOG(("Error: %s", e->errmess));
/* hmm, deja-vu */
temp = plugin_add_message_to_linked_list((plugin_b)params->browser, (plugin_p)0, &m, (struct plugin_message*)0);
LOG(("Re-Sending Message &4D540"));
xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m,
wimp_BROADCAST);
while(temp->poll == 0)
gui_poll();
if(temp->plugin != 0 && temp->reply != 0) {
/* ok, we got a reply */
LOG(("Reply to message %p: %p", temp, temp->reply));
flags = plugin_process_opening(params, temp);
plugin_remove_message_from_linked_list(temp->reply);
plugin_remove_message_from_linked_list(temp);
// xfree(m);
xfree(varval);
xfree(npm);
xfree(npl);
} else {
/* no reply so give up */
LOG(("No reply to message %p", temp));
plugin_remove_message_from_linked_list(temp);
// xfree(m);
xfree(varval);
xfree(npm);
xfree(npl);
return;
}
}
/* At this point, it's certain that we can handle this object so
* add it to the list of plugin instances.
*/
plugin_add_instance_to_list(c, bw, page, box, params, state);
/* TODO - handle other flags (see below) */
if(flags & 0x4)
plugin_create_stream(bw, params, c);
plugin_destroy_stream(bw, params, c);
}
/**
* plugin_process_opening
* process plugin_opening message flags
* NB: this is NOT externally visible.
* it's just here because it's referred to in the TODO above
*/
int plugin_process_opening(struct object_params *params,
struct plugin_message *message) {
plugin_message_opening *pmo;
params->plugin = (int)message->reply->plugin;
params->plugin_task = (unsigned int)message->reply->m->sender;
pmo = (plugin_message_opening*)&message->reply->m->data;
/* LOG(("pmo->flags = %x", pmo->flags));
if(pmo->flags & 0x1)
LOG(("accepts input focus"));
if(pmo->flags & 0x2)
LOG(("wants code fetching"));
if(pmo->flags & 0x4)
LOG(("wants data fetching"));
if(pmo->flags & 0x8)
LOG(("will delete parameters"));
if(pmo->flags & 0x10)
LOG(("still busy"));
if(pmo->flags & 0x20)
LOG(("supports extended actions"));
if(pmo->flags & 0x40)
LOG(("has helper window"));
*/
return (int)pmo->flags;
}
/**
* plugin_remove_instance
*
* A plugin is no longer required, eg. the page containing it has
* been closed.
*
* Any storage associated with state must be freed.
*/
void plugin_remove_instance(struct content *c, struct browser_window *bw,
struct content *page, struct box *box,
struct object_params *params, void **state)
{
// wimp_message *m = xcalloc(256, sizeof(char));
wimp_message m;
plugin_message_close *pmc;
struct plugin_message *temp;
char *p, *filename = strdup(params->filename);
if (params == 0) {
// xfree(m);
return;
}
pmc = (plugin_message_close*)&m.data;
pmc->flags = 0;
pmc->plugin = (plugin_p)params->plugin;
pmc->browser = (plugin_b)params->browser;
m.size = 32;
m.your_ref = 0;
m.action = message_PLUG_IN_CLOSE;
temp = plugin_add_message_to_linked_list(pmc->browser, pmc->plugin, &m, 0);
LOG(("Sending message &4D542"));
xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m,
(wimp_t)params->plugin_task);
// xfree(m);
while (temp == 0)
gui_poll();
if (temp->reply != 0){
plugin_remove_message_from_linked_list(temp->reply);
plugin_remove_message_from_linked_list(temp);
}
else {
LOG(("message_PLUG_IN_CLOSE bounced"));
plugin_remove_message_from_linked_list(temp);
}
/* delete parameters file */
xosfile_delete((char const*)params->filename, NULL, NULL, NULL, NULL, NULL);
p = strrchr((const char*)filename, 'p');
filename[(p-filename)] = 'd';
xosfile_delete((char const*)filename, NULL, NULL, NULL, NULL, NULL);
/* delete instance from list */
plugin_remove_instance_from_list(params);
}
/**
* plugin_reshape_instance
*
* The box containing the plugin has moved or resized,
* or the window containing the plugin has resized if standalone.
*/
void plugin_reshape_instance(struct content *c, struct browser_window *bw,
struct content *page, struct box *box,
struct object_params *params, void **state)
{
/* By now, we've got the plugin up and running in a nested window
* off the viewable page area. Now we want to display it in its place.
* Therefore, broadcast a Message_PlugIn_Reshape (&4D544) with the values
* given to us.
*/
// wimp_message *m = xcalloc(256, sizeof(char));
wimp_message m;
plugin_message_reshape *pmr;
os_box bbox;
bbox.x0 = box->x;
bbox.y0 = box->y;
bbox.x1 = (box->x + box->width);
bbox.y1 = (box->y + box->height);
pmr = (plugin_message_reshape*)&m.data;
pmr->flags = 0;
pmr->plugin = (plugin_p) params->plugin;
pmr->browser = (plugin_b) params->browser;
pmr->parent_window = (wimp_w) bw->window->data.browser.window;
pmr->bbox = bbox;
m.size = 36;
m.your_ref = 0;
m.action = message_PLUG_IN_RESHAPE;
LOG(("Sending Message &4D544"));
xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
// xfree(m);
LOG(("plugin_reshape_instance"));
}
static const char * const ALIAS_PREFIX = "Alias$@PlugInType_";
/**
* plugin_create_sysvar
* creates system variable from mime type
* NB: this is NOT externally visible
* it just makes sense to keep it with the ALIAS_PREFIX definition above.
*/
void plugin_create_sysvar(const char *mime_type, char* sysvar)
{
unsigned int *fv;
os_error *e;
e = xmimemaptranslate_mime_type_to_filetype(mime_type, (bits *) &fv);
sprintf(sysvar, "%s%x", ALIAS_PREFIX, fv);
}
/**
* plugin_handleable
* Tests whether we can handle an object using a browser plugin
* returns true if we can handle it, false if we can't.
*/
bool plugin_handleable(const char *mime_type)
{
char sysvar[40];
unsigned int *fv;
os_error *e;
e = xmimemaptranslate_mime_type_to_filetype(mime_type, (bits *) &fv);
if (e) {
LOG(("xmimemaptranslate_mime_type_to_filetype failed: %s", e->errmess));
return false;
}
sprintf(sysvar, "%s%x", ALIAS_PREFIX, fv);
LOG(("%s, %s", mime_type, sysvar));
if (getenv(sysvar) == 0)
return false;
return true;
}
/**
* plugin_process_data
* processes data retrieved by the fetch process
*/
void plugin_process_data(struct content *c, char *data, unsigned long size)
{
/* If the plugin requests, we send the data to it via the
* plugin stream protocol.
* Also, we should listen for Message_PlugIn_URL_Access (&4D54D)
* as the plugin may need us to retrieve URLs for it.
* We should also listen for Message_PlugIn_Closed (&4D543).
* If this occurs, the plugin has exited with an error.
* Therefore, we need to stop the fetch and exit.
*/
/* I think we should just buffer the data here, in case the
* plugin requests it sometime in the future. - James */
c->data.plugin.data = xrealloc(c->data.plugin.data, c->data.plugin.length + size);
memcpy(c->data.plugin.data + c->data.plugin.length, data, size);
c->data.plugin.length += size;
c->size += size;
}
/**
* plugin_convert
* This isn't needed by the plugin system as all the data processing is done
* externally. Therefore, just tell NetSurf that everything's OK.
*/
int plugin_convert(struct content *c, unsigned int width, unsigned int height)
{
c->status=CONTENT_STATUS_DONE;
return 0;
}
void plugin_revive(struct content *c, unsigned int width, unsigned int height)
{
}
void plugin_reformat(struct content *c, unsigned int width, unsigned int height)
{
}
/**
* plugin_destroy
*/
void plugin_destroy(struct content *c)
{
/* simply free buffered data */
xfree(c->data.plugin.data);
}
/**
* plugin_redraw
* redraw plugin on page.
*/
void plugin_redraw(struct content *c, long x, long y,
unsigned long width, unsigned long height)
{
}
/*-------------------------------------------------------------------------*/
/* Parameters file handling functions */
/*-------------------------------------------------------------------------*/
/**
* plugin_write_parameters_file
* Writes the parameters file.
* Beware, this function is long and nasty. It appears to work, however.
*/
void plugin_write_parameters_file(struct object_params *params)
{
struct plugin_params* temp;
int *time;
os_fw pfile;
int j, rsize = 0;
char *tstr;
byte pdata[4] = {0, 0, 0, 0};
/* Create the file */
xosfile_create_dir("<Wimp$ScrapDir>.WWW", 77);
xosfile_create_dir("<Wimp$ScrapDir>.WWW.NetSurf", 77);
/* path + filename + terminating NUL */
params->filename = xcalloc(strlen(getenv("Wimp$ScrapDir"))+13+10+1,
sizeof(char));
xos_read_monotonic_time((int*)&time);
tstr = xcalloc(40, sizeof(char));
sprintf(tstr, "%01u", (unsigned int)time<<8);
sprintf(params->filename, "%s.WWW.NetSurf.p%1.9s",
getenv("Wimp$ScrapDir"), tstr);
params->browser = (unsigned int)time<<8;
xfree(tstr);
LOG(("filename: %s", params->filename));
xosfind_openoutw(osfind_NO_PATH, params->filename, NULL, &pfile);
/* Write object attributes first */
/* classid is checked first */
if(params->classid != 0 && params->codetype != 0) {
/* Record Type */
plugin_populate_pdata(1, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* Record size */
rsize = 0;
rsize += (4 + 7 + 1);
rsize += (4 + strlen(params->classid));
if((strlen(params->classid)%4) != 0)
rsize += (4-(strlen(params->classid)%4));
rsize += (4 + strlen(params->codetype));
if((strlen(params->codetype)%4) != 0)
rsize += (4-(strlen(params->codetype)%4));
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
/* size */
rsize = strlen("CLASSID");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
xosgbpb_writew(pfile, (byte const*)"CLASSID", rsize, NULL);
/* pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata,
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
/* value */
/* size */
rsize = strlen(params->classid);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
xosgbpb_writew(pfile, (byte const*)params->classid, rsize, NULL);
/* pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata,
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
/* type */
/* size */
rsize = strlen(params->codetype);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
xosgbpb_writew(pfile, (byte const*)params->codetype, rsize, NULL);
/* pad to word boundary */
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata,
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
}
/* otherwise, we check the data attribute */
else if(params->data !=0 && params->type != 0) {
/* Record Type */
plugin_populate_pdata(1, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* Record size */
rsize = 0;
rsize += (4 + 4);
rsize += (4 + strlen(params->data));
if((strlen(params->data)%4) != 0)
rsize += (4-(strlen(params->data)%4));
rsize += (4 + strlen(params->type));
if((strlen(params->type)%4) != 0)
rsize += (4-(strlen(params->type)%4));
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
/* size */
rsize = strlen("DATA");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
xosgbpb_writew(pfile, (byte const*)"DATA", rsize, NULL);
/* pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata,
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
/* value */
/* size */
rsize = strlen(params->data);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
xosgbpb_writew(pfile, (byte const*)params->data, rsize, NULL);
/* pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata,
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
/* type */
/* size */
rsize = strlen(params->type);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
xosgbpb_writew(pfile, (byte const*)params->type, rsize, NULL);
/* pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata,
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
}
/* if codebase is specified, write it as well */
if(params->codebase != 0) {
/* Record Type */
plugin_populate_pdata(1, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* Record size */
rsize = 0;
rsize += (4 + 8);
rsize += (4 + strlen(params->codebase));
if((strlen(params->codebase)%4) != 0)
rsize += (4-(strlen(params->codebase)%4));
rsize += 4;
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
/* size */
rsize = strlen("CODEBASE");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
xosgbpb_writew(pfile, (byte const*)"CODEBASE", rsize, NULL);
/* pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata,
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
/* value */
/* size */
rsize = strlen(params->codebase);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* name */
xosgbpb_writew(pfile, (byte const*)params->codebase, rsize, NULL);
/* pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata,
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
/* type */
/* size */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
}
/* Iterate through the parameter list, creating the parameters
* file as we go. We can free up the memory as we go.
*/
while(params->params != 0) {
LOG(("name: %s", params->params->name == 0 ? "not set" : params->params->name));
LOG(("value: %s", params->params->value == 0 ? "not set" : params->params->value));
LOG(("type: %s", params->params->type == 0 ? "not set" : params->params->type));
LOG(("valuetype: %s", params->params->valuetype));
/* Record Type */
if(strcasecmp(params->params->valuetype, "data") == 0)
rsize = 1;
if(strcasecmp(params->params->valuetype, "ref") == 0)
rsize = 2;
if(strcasecmp(params->params->valuetype, "object") == 0)
rsize = 3;
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* Record Size */
rsize = 0;
if(params->params->name != 0) {
rsize += 4;
rsize += strlen(params->params->name);
if((strlen(params->params->name) % 4) != 0)
rsize += (4 - (strlen(params->params->name) % 4));
}
if(params->params->value != 0) {
rsize += 4;
rsize += strlen(params->params->value);
if((strlen(params->params->value) % 4) != 0)
rsize += 4 - ((strlen(params->params->value) % 4));
}
if(params->params->type != 0) {
rsize += 4;
rsize += strlen(params->params->type);
if((strlen(params->params->type) % 4) != 0)
rsize += (4 - (strlen(params->params->type) % 4));
} else {
rsize += 4;
}
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* Record Name */
if(params->params->name != 0) {
/* Size */
rsize = strlen(params->params->name);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* Name */
xosgbpb_writew(pfile, (byte const*)params->params->name, rsize, NULL);
/* Pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
}
/* Record Value */
if(params->params->value != 0) {
/* Size */
rsize = strlen(params->params->value);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* Name */
xosgbpb_writew(pfile, (byte const*)params->params->value, rsize, NULL);
/* Pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
}
/* Record Type */
if(params->params->type != 0) {
/* Size */
rsize = strlen(params->params->type);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
/* Name */
xosgbpb_writew(pfile, (byte const*)params->params->type, rsize, NULL);
/* Pad to word boundary */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
} else {
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
}
temp = params->params;
params->params = params->params->next;
xfree(temp);
}
/* Now write mandatory special parameters
*
* Case: Parameter:
*
* 0 BASEHREF
* 1 USERAGENT
* 2 UAVERSION
* 3 APIVERSION
* 4 BGCOLOR - needs fixing to work properly.
* Currently, it assumes FFFFFF00 (BBGGRR00)
*/
for(j=0; j!=5; j++) {
plugin_populate_pdata(4, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
switch(j) {
case 0: rsize = 0;
rsize += (4 + 8);
rsize += (4 + strlen(params->basehref));
if((strlen(params->basehref)%4) != 0)
rsize += (4-(strlen(params->basehref)%4));
rsize += 4;
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
rsize = strlen("BASEHREF");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"BASEHREF", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
rsize = strlen(params->basehref);
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)params->basehref, rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
break;
case 1: rsize = 0;
rsize += (4 + 9 + 3);
rsize += (4 + strlen("NetSurf"));
if((strlen("NetSurf")%4) != 0)
rsize += (4-(strlen("NetSurf")%4));
rsize += 4;
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
rsize = strlen("USERAGENT");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"USERAGENT", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
rsize = strlen("NetSurf");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"NetSurf", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
break;
case 2: rsize = 0;
rsize += (4 + 9 + 3);
rsize += (4 + strlen("0.01"));
if((strlen("0.01")%4) != 0)
rsize += (4-(strlen("0.01")%4));
rsize += 4;
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
rsize = strlen("UAVERSION");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"UAVERSION", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
rsize = strlen("0.01");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"0.01", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
break;
case 3: rsize = 0;
rsize += (4 + 10 + 2);
rsize += (4 + strlen("1.10"));
if((strlen("1.10")%4) != 0)
rsize += (4-(strlen("1.10")%4));
rsize += 4;
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
rsize = strlen("APIVERSION");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"APIVERSION", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
rsize = strlen("1.10");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"1.10", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
break;
case 4: rsize = 0;
rsize += (4 + 7 + 1);
rsize += (4 + strlen("FFFFFF00"));
if((strlen("FFFFFF00")%4) != 0)
rsize += (4-(strlen("FFFFFF00")%4));
rsize += 4;
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
rsize = strlen("BGCOLOR");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"BGCOLOR", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
rsize = strlen("FFFFFF00");
plugin_populate_pdata(rsize, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosgbpb_writew(pfile, (byte const*)"FFFFFF00", rsize, NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
break;
}
}
/* Write terminator */
plugin_populate_pdata(0, (byte *)&pdata);
xosgbpb_writew(pfile, pdata, 4, NULL);
xosfind_closew(pfile);
}
/**
* plugin_populate_pdata
* helper function for plugin_write_parameters_file
*/
void plugin_populate_pdata(int rsize, byte *pdata) {
pdata[0] = rsize & 0xff;
pdata[1] = (rsize >> 0x08) & 0xff;
pdata[2] = (rsize >> 0x10) & 0xff;
pdata[3] = (rsize >> 0x18) & 0xff;
}
/*-------------------------------------------------------------------------*/
/* Plugin Stream handling functions */
/*-------------------------------------------------------------------------*/
/**
* plugin_create_stream
* creates a plugin stream
*/
void plugin_create_stream(struct browser_window *bw, struct object_params *params, struct content *c) {
// wimp_message *m = xcalloc(256, sizeof(char));
wimp_message m;
plugin_message_stream_new *pmsn;
struct plugin_message *temp;
int offset = 0;
unsigned char *pchar = (unsigned char*)&m.data;
pmsn = (plugin_message_stream_new*)&m.data;
pmsn->flags = 2;
pmsn->plugin = (plugin_p)params->plugin;
pmsn->browser = (plugin_b)params->browser;
pmsn->browser_stream = (plugin_bs)params->browser;
pmsn->end = c->data.plugin.length;
pmsn->last_modified_date = 0;
pmsn->notify_data = 0;
offset = 64;
pmsn->url.offset = offset;
strncpy((char*)&pchar[offset], c->url, (unsigned int)236-offset);
offset = offset + strlen(c->url) + 1;
if (offset > 235) {
LOG(("URL too long"));
// xfree(m);
return;
}
offset = (offset + 3) / 4 * 4;
pmsn->mime_type.offset = offset;
strncpy((char*)&pchar[offset], c->mime_type, (unsigned int)236-offset);
offset = offset + strlen(c->mime_type) + 1;
if (offset > 235) {
LOG(("mime_type too long"));
// xfree(m);
return;
}
pmsn->target_window.offset = 0;
m.size = (20 + offset + 3) / 4 * 4;
m.your_ref = 0;
m.action = message_PLUG_IN_STREAM_NEW;
temp = plugin_add_message_to_linked_list(pmsn->browser, pmsn->plugin, &m, 0);
LOG(("message length = %d", m.size));
LOG(("Sending message &4D548"));
xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m, (wimp_t)params->plugin_task);
while(temp->poll == 0)
gui_poll();
pmsn = (plugin_message_stream_new*)&temp->reply->m->data;
params->browser_stream = params->browser;
params->plugin_stream = (int)pmsn->stream;
LOG(("%d, %d, %d", (int)pmsn->stream, params->plugin_stream, params->browser_stream));
if((pmsn->flags & 0x02) | (pmsn->flags & 0x03)) {
plugin_write_stream_as_file(bw, params, c);
}
/* clean up */
plugin_remove_message_from_linked_list(temp->reply);
plugin_remove_message_from_linked_list(temp);
// xfree(m);
}
/**
* plugin_write_stream_as_file
* writes a stream as a file
*/
void plugin_write_stream_as_file(struct browser_window *bw, struct object_params *params, struct content *c) {
// wimp_message *m = xcalloc(256, sizeof(char));
wimp_message m;
plugin_message_stream_as_file *pmsaf;
int offset = 0;
unsigned int filetype;
unsigned char *pchar = (unsigned char*)&m.data;
char *filename = strdup(params->filename), *p;
pmsaf = (plugin_message_stream_as_file*)&m.data;
pmsaf->flags = 0;
pmsaf->plugin = (plugin_p)params->plugin;
pmsaf->browser = (plugin_b)params->browser;
pmsaf->stream = (plugin_s)params->plugin_stream;
pmsaf->browser_stream = (plugin_bs)params->browser_stream;
pmsaf->end = 0;
pmsaf->last_modified_date = 0;
pmsaf->notify_data = 0;
offset = 60;
pmsaf->url.offset = offset;
strncpy((char*)&pchar[offset], c->url, (unsigned int)236-offset);
offset = offset + strlen(c->url) + 1;
if (offset > 235) {
LOG(("URL too long"));
// xfree(m);
return;
}
offset = (offset + 3) / 4 * 4;
pmsaf->filename.offset = offset;
p = strrchr((const char*)filename, 'p');
filename[(p-filename)] = 'd';
strncpy((char*)&pchar[offset], filename, (unsigned int)236-offset);
offset = offset + strlen(filename) + 1;
if (offset > 235) {
LOG(("filename too long"));
// xfree(m);
return;
}
m.size = (20 + offset + 3) / 4 * 4;
m.your_ref = 0;
m.action = message_PLUG_IN_STREAM_AS_FILE;
xmimemaptranslate_mime_type_to_filetype(c->mime_type, (bits *) &filetype);
xosfile_save_stamped((char const*)filename, filetype, c->data.plugin.data, c->data.plugin.data + c->data.plugin.length);
LOG(("message length = %d", m.size));
LOG(("Sending message &4D54C"));
xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
// xfree(m);
}
/**
* plugin_destroy_stream
* destroys a plugin stream
*/
void plugin_destroy_stream(struct browser_window *bw, struct object_params *params, struct content *c) {
// wimp_message *m = xcalloc(256, sizeof(char));
wimp_message m;
plugin_message_stream_destroy *pmsd;
int offset = 0;
unsigned char *pchar = (unsigned char*)&m.data;
pmsd = (plugin_message_stream_destroy*)&m.data;
pmsd->flags = 0;
pmsd->plugin = (plugin_p)params->plugin;
pmsd->browser = (plugin_b)params->browser;
pmsd->stream = (plugin_s)params->plugin_stream;
pmsd->browser_stream = (plugin_bs)params->browser_stream;
pmsd->end = 0;
pmsd->last_modified_date = 0;
pmsd->notify_data = 0;
pmsd->reason = plugin_STREAM_DESTROY_FINISHED;
offset = 60;
pmsd->url.offset = offset;
strncpy((char*)&pchar[offset], c->url, (unsigned int)236-offset);
offset = offset + strlen(c->url) + 1;
if (offset > 235) {
LOG(("URL too long"));
// xfree(m);
return;
}
m.size = (20 + offset + 3) / 4 * 4;
m.your_ref = 0;
m.action = message_PLUG_IN_STREAM_DESTROY;
LOG(("Sending message &4D549"));
xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
// xfree(m);
}
/*-------------------------------------------------------------------------*/
/* Linked List handling functions */
/*-------------------------------------------------------------------------*/
/**
* plugin_add_message_to_linked_list
* adds a message to the list
*/
struct plugin_message *plugin_add_message_to_linked_list(plugin_b browser, plugin_p plugin, wimp_message *m, struct plugin_message *reply) {
struct plugin_message *npm = xcalloc(1, sizeof(*npm));
npm->poll = 0;
npm->browser = browser;
npm->plugin = plugin;
npm->m = m;
npm->reply = reply;
npm->prev = pmlist->prev;
npm->next = pmlist;
pmlist->prev->next = npm;
pmlist->prev = npm;
LOG(("Added Message: %p", npm));
return pmlist->prev;
}
/**
* plugin_remove_message_from_linked_list
* removes a message from the list
*/
void plugin_remove_message_from_linked_list(struct plugin_message* m) {
m->prev->next = m->next;
m->next->prev = m->prev;
LOG(("Deleted Message: %p", m));
xfree(m);
}
/**
* plugin_get_message_from_linked_list
* retrieves a message from the list
* returns NULL if no message is found
*/
struct plugin_message *plugin_get_message_from_linked_list(int ref) {
struct plugin_message *npm;
for(npm = pmlist->next; npm != pmlist && npm->m->my_ref != ref;
npm = npm->next)
LOG(("my_ref: %d, ref: %d", npm->m->my_ref, ref));
LOG(("my_ref: %d, ref: %d", npm->m->my_ref, ref));
if(npm != pmlist) {
LOG(("Got message: %p", npm));
return npm;
}
return NULL;
}
/**
* plugin_add_instance_to_list
* Adds a plugin instance to the list of plugin instances.
*/
void plugin_add_instance_to_list(struct content *c, struct browser_window *bw, struct content *page, struct box *box, struct object_params *params, void **state) {
struct plugin_list *npl = xcalloc(1, sizeof(*npl));
npl->c = c;
npl->bw = bw;
npl->page = page;
npl->box = box;
npl->params = params;
npl->state = state;
npl->prev = plist->prev;
npl->next = plist;
plist->prev->next = npl;
plist->prev = npl;
}
/**
* plugin_remove_instance_from_list
* Removes a plugin instance from the list
*/
void plugin_remove_instance_from_list(struct object_params *params) {
struct plugin_list *temp =
plugin_get_instance_from_list((plugin_b)params->browser,
(plugin_p)params->plugin);
if(temp != NULL) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
xfree(temp);
}
}
/**
* plugin_get_instance_from_list
* retrieves an instance of a plugin from the list
* returns NULL if no instance is found
*/
struct plugin_list *plugin_get_instance_from_list(plugin_b browser, plugin_p plugin) {
struct plugin_list *npl;
for(npl = plist->next; (npl != plist)
&& (((plugin_b)npl->params->browser != browser)
&& ((plugin_p)npl->params->plugin != plugin));
npl = npl->next)
;
if(npl != plist)
return npl;
return NULL;
}
/*-------------------------------------------------------------------------*/
/* WIMP Message processing functions */
/*-------------------------------------------------------------------------*/
/**
* plugin_msg_parse
* parses wimp messages
*/
void plugin_msg_parse(wimp_message *message, int ack)
{
LOG(("Parsing message"));
switch(message->action) {
case message_PLUG_IN_OPENING:
plugin_opening(message);
break;
case message_PLUG_IN_CLOSED:
plugin_closed(message);
break;
case message_PLUG_IN_RESHAPE_REQUEST:
plugin_reshape_request(message);
break;
case message_PLUG_IN_FOCUS:
// plugin_focus();
break;
case message_PLUG_IN_URL_ACCESS:
// plugin_url_access();
break;
case message_PLUG_IN_STATUS:
plugin_status(message);
break;
case message_PLUG_IN_BUSY:
// plugin_busy();
break;
/* OSLib doesn't provide this, as it's
* reasonably new and not obviously documented.
* We ignore it for now.
case message_PLUG_IN_INFORMED:
*/
case message_PLUG_IN_STREAM_NEW:
plugin_stream_new(message);
break;
case message_PLUG_IN_STREAM_WRITE:
// plugin_stream_write();
break;
case message_PLUG_IN_STREAM_WRITTEN:
// plugin_stream_written();
break;
case message_PLUG_IN_STREAM_DESTROY:
// plugin_stream_destroy();
break;
/* These cases occur when a message is bounced
* For simplicity, we do nothing unless the message came in
* a wimp_USER_MESSAGE_ACKNOWLEDGE (ie ack = 1)
*/
case message_PLUG_IN_OPEN:
if(ack)
plugin_open(message);
break;
case message_PLUG_IN_CLOSE:
if(ack)
plugin_close(message);
break;
case message_PLUG_IN_RESHAPE:
case message_PLUG_IN_STREAM_AS_FILE:
case message_PLUG_IN_NOTIFY:
case message_PLUG_IN_ABORT:
case message_PLUG_IN_ACTION:
default:
break;
}
}
/**
* plugin_open
* handles receipt of plugin_open messages
*/
void plugin_open(wimp_message *message) {
struct plugin_message *npm = plugin_get_message_from_linked_list(message->my_ref);
LOG(("Acknowledgement of %p", npm));
/* notify plugin_open message entry in list */
if (npm != NULL)
npm->poll = 1;
}
/**
* plugin_opening
* handles receipt of plugin_open messages
*/
void plugin_opening(wimp_message *message) {
struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
struct plugin_message *reply;
plugin_message_opening *pmo = (plugin_message_opening*)&message->data;
/* add this message to linked list */
reply = plugin_add_message_to_linked_list(pmo->browser, pmo->plugin, message, 0);
/* notify plugin_open message entry in list */
if (npm != NULL) {
npm->poll = 1;
npm->plugin = pmo->plugin;
npm->reply = reply;
}
}
/**
* plugin_close
* handles receipt of plugin_close messages
*/
void plugin_close(wimp_message *message) {
struct plugin_message *npm = plugin_get_message_from_linked_list(message->my_ref);
/* notify plugin_open message entry in list */
if (npm != NULL)
npm->poll = 1;
}
/**
* plugin_closed
* handles receipt of plugin_closed messages
*/
void plugin_closed(wimp_message *message) {
struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
struct plugin_message *reply;
plugin_message_closed *pmc = (plugin_message_closed*)&message->data;
/* add this message to linked list */
reply = plugin_add_message_to_linked_list(pmc->browser, pmc->plugin, message, 0);
/* notify plugin_open message entry in list */
if (npm != NULL) {
npm->poll = 1;
npm->reply = reply;
}
}
/**
* plugin_reshape_request
* handles receipt of plugin_reshape_request messages
*/
void plugin_reshape_request(wimp_message *message) {
struct plugin_message *npm;
struct plugin_list *npl;
plugin_message_reshape_request *pmrr = (plugin_message_reshape_request*)&message->data;
/* add this message to linked list */
npm = plugin_add_message_to_linked_list(pmrr->browser, pmrr->plugin, message, 0);
/* TODO - need to find a way of forcing the browser to resize the
* box containing this object. Then issue a Plugin_Reshape.
*/
npl = plugin_get_instance_from_list(pmrr->browser, pmrr->plugin);
plugin_remove_message_from_linked_list(npm); /* lose this later */
LOG(("requested (width, height): (%d, %d)", pmrr->size.x, pmrr->size.y));
}
/**
* plugin_stream_new
* handles receipt of plugin_stream_new messages
*/
void plugin_stream_new(wimp_message *message) {
struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
struct plugin_message *reply;
plugin_message_stream_new *pmsn = (plugin_message_stream_new*)&message->data;
/* add this message to linked list */
reply = plugin_add_message_to_linked_list(pmsn->browser, pmsn->plugin, message, 0);
/* notify plugin_open message entry in list */
if(npm != NULL) {
npm->poll = 1;
npm->plugin = pmsn->plugin;
npm->reply = reply;
}
}
/**
* plugin_status
* handles receipt of plugin_status messages
*/
void plugin_status(wimp_message *message) {
plugin_message_status *pms = (plugin_message_status*)&message->data;
struct plugin_list *npl = plugin_get_instance_from_list(pms->browser, pms->plugin);
gui_window_set_status(npl->bw->window,
(const char*)plugin_get_string_value(pms->message,
(char*)pms));
}
/**
* plugin_get_string_value
* utility function to grab string data from plugin message blocks
*/
char *plugin_get_string_value(os_string_value string, char *msg) {
if(string.offset == 0 || string.offset > 256) {
return string.pointer;
}
return &msg[string.offset];
}