/* Copyright 1997 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /***************************************************/ /* File : Object.c */ /* */ /* Purpose: Handling OBJECT, APPLET and EMBED. */ /* */ /* Author : A.D.Hodgkinson */ /* */ /* History: 05-Oct-97: Created. */ /***************************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "swis.h" #include "flex.h" #include "HTMLLib.h" /* HTML library API, Which will include html2_ext.h, tags.h and struct.h */ #include "wimp.h" #include "wimplib.h" #include "event.h" #include "toolbox.h" #include "svcprint.h" #include "Global.h" #include "FromROSLib.h" #include "Utils.h" #include "Browser.h" #include "ChoiceDefs.h" #include "Fetch.h" /* (Which itself includes URLstat.h) */ #include "FetchHTML.h" #include "Filetypes.h" #include "Images.h" #include "Memory.h" #include "MimeMap.h" #include "MiscDefs.h" #include "PlugIn.h" #include "Redraw.h" #include "Reformat.h" #include "TokenUtils.h" #include "Toolbars.h" #include "URLveneer.h" #include "Object.h" /* Static function prototypes */ static int object_get_token_object (browser_data * b, HStream * t); static _kernel_oserror * object_get_object_size (browser_data * b, int object, BBox * size); static _kernel_oserror * object_set_object_size (browser_data * b, int object, BBox * size); static int object_get_object_position (browser_data * b, int object, int * x, int * y); static _kernel_oserror * object_get_object_plugin (browser_data * b, int object, unsigned int * plugin_instance, unsigned int * plugin_task); static _kernel_oserror * object_set_object_plugin (browser_data * b, int object, unsigned int plugin_instance, unsigned int plugin_task); /*************************************************/ /* object_new_object() */ /* */ /* Adds a structure for a new Object to a */ /* browser's array of Objects. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* to add to; */ /* */ /* Pointer to a token representing */ /* the Object (OBJECT, EMBED or */ /* APPLET tag). */ /*************************************************/ _kernel_oserror * object_new_object(browser_data * b, HStream * t) { const char * data; const char * type; /* If this isn't an Object token, do nothing (well, */ /* complain about it in TRACE builds). */ if (!t || !ISOBJECT(t)) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Token %08x passed to object_new_object does not represent an OBJECT, APPLET or EMBED tag", (int) t); return &erb; #endif return NULL; } /* Allocate memory for the item */ RetError(memory_set_chunk_size(b, NULL, CK_OBJB, (b->nobjects + 1) * sizeof(object_info))); /* Fill in the new item */ b->odata[b->nobjects].plugin_instance_handle = 0; b->odata[b->nobjects].plugin_task_handle = 0; b->odata[b->nobjects].token = t; /* Until this is seen by the user, open it off-screen to avoid */ /* having to send out lots of reposition calls during the main */ /* page reformat. */ b->odata[b->nobjects].x = -1; b->odata[b->nobjects].y = -1; /* Initially set invalid widths / heights so that it must be */ /* worked out properly later. */ b->odata[b->nobjects].w = -1; b->odata[b->nobjects].h = -1; /* Set up initial flags values */ b->odata[b->nobjects].isimage = 0; b->odata[b->nobjects].isplugin = 0; b->odata[b->nobjects].broadcast_sent = 0; /* Finally, increment the objects counter */ b->nobjects++; /* Now deal with data types we can handle inline */ data = HtmlOBJECTdata(t); type = HtmlOBJECTtype(t); if (data && *data) { int filetype; /* If we have a Mime type, use it */ if (type && *type) { if (mimemap_mime_to_riscos(type, &filetype)) filetype = FileType_DATA; } /* Otherwise, try to work it out from the filename extension */ else { const char * ext; ext = data + strlen(data) - 1; while (ext >= data && *ext != '.') ext--; if (*ext == '.') { if (mimemap_extension_to_riscos(ext, &filetype)) filetype = FileType_DATA; } else filetype = FileType_DATA; } /* Is it an image we can handle? */ if ( filetype == FileType_PNG || filetype == FileType_GIF || filetype == FileType_JPEG || filetype == FileType_TIFF || filetype == FileType_XBM || filetype == FileType_BMP ) { const char * current; const char * newdata; /* Must relativise the data URL... */ current = browser_fetch_url(b); if (!current) current = browser_current_url(b); if (current) { newdata = HtmlRelativiseURL(current, data, t); if (newdata) { /* If we've managed all that, call image_new_image */ RetError(image_new_image(b, newdata, t, 0)); b->odata[b->nobjects - 1].isimage = 1; return NULL; } } } } /* Deal with external objects */ else data = HtmlOBJECTclassid(t); if (data && *data) { int cannot_handle = 0; /* Well OK, this looks like a Plug-In. But can we handle it? */ /* First, check for Active-X. */ if (!strncmp(data, "clsid:", 6)) cannot_handle = 1; /* Otherwise, check a Plug-In exists to handle the data type */ else { const char * type = HtmlOBJECTcodetype(t); const char * ext = strrchr(data, '.'); /* Can't handle it if there's no extension or code type */ if (!ext && (!type || (type && !*type))) cannot_handle = 1; else { int filetype; /* Can't handle it if we don't have a Mime map entry for it */ if (type) { if (mimemap_mime_to_riscos(type, &filetype)) cannot_handle = 1; } else { if (mimemap_extension_to_riscos(ext, &filetype)) cannot_handle = 1; } if (!cannot_handle) { char var[32]; _kernel_swi_regs r; /* Final check is to see if there's an Alias$@PlugInType_xxx variable */ sprintf(var, "Alias$@PlugInType_%03X", filetype); r.r[0] = (int) var; r.r[1] = (int) NULL; r.r[2] = -1; r.r[3] = 0; r.r[4] = 0; /* *Not* _swix, we want the R2 value of 0 for 'unset'... */ _kernel_swi(OS_ReadVarVal, &r, &r); if (!r.r[2]) cannot_handle = 1; } } } /* If we can handle it, flag this as a Plug-In */ if (!cannot_handle) b->odata[b->nobjects - 1].isplugin = 1; /* Otherwise, use the alternative HTML stream here */ else { int depth, line, chunk; token_path * path = NULL; // For now - security blanket... /* Can't do anything if the next token has been preprocessed [somehow] */ if (t->next && t->next->flags == HFlags_DealtWithToken) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; StrNCpy0(erb.errmess, "Can't replace this object tag as later tokens have already been preprocessed, in object_new_object"); show_error_ret(&erb); #else t = t; #endif } else { /* What line was the token in? */ depth = tokenutils_line_range(b, t, &line, &chunk, NULL, NULL, &path); if (line >= 0) { /* If the line was found and we have a depth, the line */ /* is in a table - find the base parent line of the */ /* table, so we can reformat it. */ if (depth) line = path[depth - 1].line; } if (path) free(path); /* Right, only have to reformat if the token was in the */ /* line list. */ if (line >= 0) reformat_format_from(b, line - 1, 0, -1); /* We now know that the object is no longer in any line */ /* list, so it's safe to preprocess the alternate HTML */ /* stream and place that under the token. */ t->flags |= HFlags_IgnoreObject; /* Discard the new object */ b->nobjects --; memory_set_chunk_size(b, NULL, CK_OBJB, (b->nobjects + 1) * sizeof(object_info)); if (HtmlOBJECTstream(t)) { // Eeek! Recursive calls back to this routine! // // HStream * alt = HtmlOBJECTstream(t); // // /* Preprocess the stream */ // // // Of course, this probably breaks forms if extra form fields // // are present as part of an ongoing FORM tag. // // while (alt) // { // fetch_preprocess_token(b, alt); // // alt = alt->next; // } // /* Move it into the main token list */ HtmlReplaceOBJECT(t); /* That's it; any subsequent reformatting takes care of the rest */ return NULL; } } } } /* If this is a Plug-In, and we're supposed to launch them */ /* as soon as possible, then launch it now. */ if ( b->odata[b->nobjects - 1].isplugin && choices.support_object && choices.plugin_control == Choices_PlugIns_ASAP ) { BBox position; RetError(object_get_object_size(b, b->nobjects - 1, &position)); /* Object position is currently invalid, so hide the Plug-In */ /* by moving it off the top of the work area. */ position.xmax = (position.xmax - position.xmin); position.xmin = 0; position.ymax = (position.ymax - position.ymin) + 0x1000; /* 0x1000 to be (very) safe */ position.ymin = 0x1000; b->odata[b->nobjects - 1].broadcast_sent = 1; /* Don't try over and over if the first gives an error */ RetError(plugin_add_queue_item(b, t, &position)); } return NULL; } /*************************************************/ /* object_discard() */ /* */ /* Discards all Objects held by a given browser. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Objects. */ /*************************************************/ _kernel_oserror * object_discard(browser_data * b) { _kernel_oserror * e = NULL; _kernel_oserror * local; int i; /* Close down any Plug-Ins */ for (i = 0; i < b->nobjects; i++) { if ( b->odata[i].isplugin && b->odata[i].broadcast_sent && b->odata[i].plugin_task_handle ) { unsigned int instance; e = plugin_obtain_instance(b, b->odata[i].token, &instance); if (!e) { e = plugin_send_close(instance, b->odata[i].plugin_task_handle, b->odata[i].plugin_instance_handle); } } } plugin_flush_instance_entries(b); /* Only set 'e' from the queue flush if the above call didn't */ /* generate an error. */ local = plugin_flush_queue(b, 1); if (!e) e = local; /* Remove the Objects themselves. */ b->nobjects = 0; memory_set_chunk_size(b, NULL, CK_OBJB, 0); return e; } /*************************************************/ /* object_get_token_object() */ /* */ /* Return the number of the Object represented */ /* in the given browser by the given token. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to a token representing */ /* the Object (OBJECT, EMBED or */ /* APPLET tag). */ /* */ /* Returns: Number of the Object from 0 to */ /* number of Objects minus 1, or -1 */ /* if the Object cannot be found. */ /*************************************************/ static int object_get_token_object(browser_data * b, HStream * t) { int found = -1; int i; /* If this isn't an Object token, do nothing (well, */ /* complain about it in TRACE builds). */ if (!t || !ISOBJECT(t)) { #ifdef TRACE if (!ISOBJECT(t)) { erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Token %08x passed to object_get_token_object does not represent an OBJECT, APPLET or EMBED tag", (int) t); show_error_ret(&erb); } #endif return -1; } /* Otherwise, try to find the item */ for (i = 0; i < b->nobjects; i++) { if (b->odata[i].token == t) { found = i; break; } } return found; } /*************************************************/ /* object_get_object_size() */ /* */ /* Returns the size of a given Object. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* to add to; */ /* */ /* Number of the Object, from 0 to */ /* number of Objects minus 1; */ /* */ /* Pointer to a BBox, in which the */ /* size of the Object will be */ /* written. */ /*************************************************/ static _kernel_oserror * object_get_object_size(browser_data * b, int object, BBox * size) { HStream * tp; /* Can't do anything without a bounding box! */ if (!size) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; strcpy(erb.errmess, "Null bounding box pointer passed to object_get_object_size"); return &erb; #endif return NULL; } /* Fill in zeros to start with */ size->xmin = size->ymin = 0; size->xmax = size->ymax = 0; /* Is this a valid object number? */ if (object < 0 || object >= b->nobjects) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Invalid object number %d for passed to object_get_object_size (browser %08x, nobjects = %d)", object, (int) b, b->nobjects); return &erb; #endif return NULL; } /* If this is an image, return through the image sizing routines */ if (b->odata[object].isimage) { return image_get_token_image_size(b, b->odata[object].token, size); } /* Find its size */ tp = b->odata[object].token; /* If we haven't already, work this out */ if (b->odata[object].w < 0 || b->odata[object].h < 0) { int w, h; int available_w = redraw_display_width (b, b->cell); int available_h = redraw_display_height(b, b->cell); /* Deal with % specifiers as well as pixels */ if (OBJECT_HAS_WIDTH(tp)) { switch (OBJECT_WIDTH_UNITS(tp)) { default: case UNITS_PIXELS: w = OBJECT_WIDTH(tp) * 2; break; case UNITS_PERCENT: w = available_w * OBJECT_WIDTH(tp) / 100; break; } } else w = 0; if (OBJECT_HAS_HEIGHT(tp)) { switch (OBJECT_HEIGHT_UNITS(tp)) { default: case UNITS_PIXELS: h = OBJECT_HEIGHT(tp) * 2; break; case UNITS_PERCENT: h = available_h * OBJECT_HEIGHT(tp) / 100; break; } } else h = 0; size->xmax = w; size->ymax = h; b->odata[object].w = w; b->odata[object].h = h; } /* Otherwise, get the prestored value */ else { size->xmax = b->odata[object].w; size->ymax = b->odata[object].h; } /* Don't allow zero in any direction */ if (size->xmax == 0 || size->ymax == 0) { const char * text = HtmlOBJECTstandby(b->odata[object].token); reformat_get_placeholder_size(b, b->odata[object].token, text, size); b->odata[object].w = size->xmax - size->xmin; b->odata[object].h = size->ymax - size->ymin; } return NULL; } /*************************************************/ /* object_get_token_object_size() */ /* */ /* Returns the size of a given Object. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to a token representing */ /* the Object (OBJECT, EMBED or */ /* APPLET tag); */ /* */ /* Pointer to a BBox, in which the */ /* size of the Object will be */ /* written. */ /*************************************************/ _kernel_oserror * object_get_token_object_size(browser_data * b, HStream * t, BBox * size) { return object_get_object_size(b, object_get_token_object(b, t), size); } /*************************************************/ /* object_set_object_size() */ /* */ /* Sets the size of a given Object. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Number of the Object, from 0 to */ /* number of Objects minus 1; */ /* */ /* Pointer to a BBox, from which the */ /* xmax - xmin and ymax - ymin */ /* values are used to set the size. */ /*************************************************/ static _kernel_oserror * object_set_object_size(browser_data * b, int object, BBox * size) { int width, height; /* Can't do anything without a bounding box! */ if (!size) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; strcpy(erb.errmess, "Null bounding box pointer passed to object_get_object_size"); return &erb; #endif return NULL; } /* Work out the width and height */ width = size->xmax - size->xmin; height = size->ymax - size->ymin; /* Is this a valid object number? */ if (object < 0 || object >= b->nobjects) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Invalid object number %d for passed to object_get_object_size (browser %08x, nobjects = %d)", object, (int) b, b->nobjects); return &erb; #endif return NULL; } /* If this is an image, need to set the image's size */ if (b->odata[object].isimage) RetError(image_set_token_image_size(b, b->odata[object].token, size)); /* Set also the width and height values for the Object */ b->odata[object].w = width; b->odata[object].h = height; return NULL; } /*************************************************/ /* object_set_token_object_size() */ /* */ /* Sets the size of a given Object. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to a token representing */ /* the Object (OBJECT, EMBED or */ /* APPLET tag); */ /* */ /* Pointer to a BBox, from which the */ /* xmax - xmin and ymax - ymin */ /* values are used to set the size. */ /*************************************************/ _kernel_oserror * object_set_token_object_size(browser_data * b, HStream * t, BBox * size) { return object_set_object_size(b, object_get_token_object(b, t), size); } /*************************************************/ /* object_get_object_position() */ /* */ /* Returns the x and y fields of the object_info */ /* structure for a given Object. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Number of the Object; */ /* */ /* Pointer to an int, in which the */ /* X coordinate is returned; */ /* */ /* Pointer to an int, in which the */ /* Y coordinate is returned. */ /* */ /* Returns: 1 if the object number is invalid */ /* or 0 for success. */ /* */ /* Assumes: Neither pointer is NULL. */ /*************************************************/ static int object_get_object_position(browser_data * b, int object, int * x, int * y) { if (object < 0 || object >= b->nobjects) return 1; *x = b->odata[object].x; *y = b->odata[object].y; return 0; } /*************************************************/ /* object_get_token_object_position() */ /* */ /* Returns the x and y fields of the object_info */ /* structure for a given Object. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to the token representing */ /* the Object; */ /* */ /* Pointer to an int, in which the */ /* X coordinate is returned; */ /* */ /* Pointer to an int, in which the */ /* Y coordinate is returned. */ /* */ /* Returns: 1 if the object could not be */ /* found from the given token, or 0 */ /* for success. */ /* */ /* Assumes: Neither pointer is NULL. */ /*************************************************/ int object_get_token_object_position(browser_data * b, HStream * t, int * x, int * y) { int object = object_get_token_object(b, t); return object_get_object_position(b, object, x, y); } /*************************************************/ /* object_set_token_object_position() */ /* */ /* Sets the x and y fields of the object_info */ /* structure for a given Object, so that it may */ /* be [partially] plotted during a fetch. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the object; */ /* */ /* Pointer to the token representing */ /* the Object; */ /* */ /* X coordinate (window coords); */ /* */ /* Y coordinate (window coords). */ /* */ /* Returns: Number of the Object that was */ /* changed, or -1 if none could be */ /* found for the given token. */ /*************************************************/ int object_set_token_object_position(browser_data * b, HStream * t, int x, int y) { int object = object_get_token_object(b, t); #ifdef TRACE if (tl & (1u<<30)) { char debugbuf[1024]; sprintf(debugbuf,"object_set_token_object_positon: Called for %p, %p at %d, %d",b,t,x,y); Printf("%s\n",debugbuf); } #endif /* If an object was found, set the x and y coordinates */ if (object >= 0) { int oldx, oldy; oldx = b->odata[object].x; oldy = b->odata[object].y; /* *Don't* invalidate x and y positions for Objects; this causes */ /* too many reshape messages for some PlugIns and can lead to */ /* items left with out-of-date position information. */ /* */ /* Objects are initialised to be in an invalidated position, of */ /* course, so still need to check for that later in the code. */ if (x != -1 && y != -1) { b->odata[object].x = x; b->odata[object].y = y; } /* If this is is acting as an image, need to update */ /* the image structure too. */ if (b->odata[object].isimage) image_set_token_image_position(b, t, x, y); /* If this item is a Plug-In, this could be the first time we've */ /* known for sure what position the item should be plotted at; */ /* pr we may want to tell the Plug-In to move to a new position. */ if (b->odata[object].isplugin) { BBox position; #ifdef TRACE if (tl & (1u<<30)) Printf("object_set_token_object_positon: Is Plug-In\n"); #endif show_error_ret(object_get_object_size(b, object, &position)); /* If this is the first time we've tried to set a position for */ /* the Object and a broadcast to start up an associated */ /* Plug-In has not yet been sent, add the Plug-In to the */ /* 'ready to launch' queue. */ if (!b->odata[object].broadcast_sent) { int start_now = 0; /* Only do this for valid Object positions */ if (x >= 0) { /* Object position is valid, we can place it in the right position initially */ position.xmin += x; position.ymin += y; position.xmax += x; position.ymax += y; if (choices.plugin_control != Choices_PlugIns_Never && choices.support_object) start_now = 1; } if (start_now) { b->odata[object].broadcast_sent = 1; /* Don't try over and over if the first gives an error */ #ifdef TRACE if (tl & (1u<<30)) Printf("object_set_token_object_positon: Starting Plug-In\n"); #endif show_error_ret(plugin_add_queue_item(b, t, &position)); } #ifdef TRACE else if (tl & (1u<<30)) Printf("object_set_token_object_position: Choices say not to start Plug-In yet\n"); #endif } /* If the Plug-In has been started, and the position of the Object */ /* has changed, tell the Plug-In to move. */ else if ( ( oldx != x || oldy != y ) && b->odata[object].plugin_task_handle ) { unsigned int instance; if (x < 0) { /* Object position is invalid */ position.xmax = (position.xmax - position.xmin); position.xmin = 0; position.ymax = (position.ymax - position.ymin) + 0x1000; /* 0x1000 to be (very) safe */ position.ymax = 0x1000; } else { /* Object position has been updated */ position.xmin += x; position.ymin += y; position.xmax += x; position.ymax += y; } /* Send the reshape message */ #ifdef TRACE if (tl & (1u<<30)) Printf("object_set_token_object_positon: Moving Plug-In\n"); #endif if (!plugin_obtain_instance(b, b->odata[object].token, &instance)) { show_error_ret(plugin_send_original_reshape(instance, b->odata[object].plugin_task_handle, b->odata[object].plugin_instance_handle, &position)); } } } } #ifdef TRACE if (tl & (1u<<30)) Printf("object_set_token_object_positon: Successful, returning Object number %d\n",object); #endif return object; } /*************************************************/ /* object_return_info() */ /* */ /* Return information on an Object identified by */ /* a Plug-In instance handle. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* holding the Objects to search; */ /* */ /* Plug-In instance handle; */ /* */ /* Pointer to an HStream *, in which */ /* the token the Object is represen- */ /* ting is written; */ /* */ /* Pointer to an int, in which the */ /* Plug-In task handle for this */ /* Object is written. */ /* */ /* Returns: Returns 1 if the item was found, */ /* else 0. If 0, the contents of the */ /* given pointers are not changed. */ /* */ /* Assumes: Either of the last two pointers */ /* may be NULL. */ /*************************************************/ int object_return_info(browser_data * b, unsigned int plugin_instance_handle, HStream ** token, unsigned int * plugin_task) { int i; for (i = 0; i < b->nobjects; i++) { if (b->odata[i].plugin_instance_handle == plugin_instance_handle) { /* Found it */ if (token) *token = b->odata[i].token; if (plugin_task) *plugin_task = b->odata[i].plugin_task_handle; return 1; } } /* Found nothing */ return 0; } /*************************************************/ /* object_get_token_object_box() */ /* */ /* Returns a bounding box filled in with parent */ /* window work area coordinates for a given */ /* Object. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to the token representing */ /* the Object; */ /* */ /* Pointer to a BBox to return the */ /* work area coordinates describing */ /* the Object's size. */ /* */ /* Returns: 1 for failure, 0 for success. */ /*************************************************/ int object_get_token_object_box(browser_data * b, HStream * t, BBox * box) { int object = object_get_token_object(b, t); int x, y; if (object < 0 || object >= b->nobjects || !box) return 1; /* Get the Object bounding box */ if (object_get_object_size(b, object, box)) return 1; /* Get the Object position */ if (object_get_object_position(b, object, &x, &y)) return 1; /* Return if the Object position is invalidated at the moment */ if (x < 0) return 1; /* Otherwise add the coordinates */ box->xmin += x; box->ymin += y; box->xmax += x; box->ymax += y; return 0; } /*************************************************/ /* object_get_object_plugin() */ /* */ /* Returns details of any Plug-In associated */ /* with a given Object (referenced by number). */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Number of the Object; */ /* */ /* Pointer to an int, in which the */ /* Plug-In instance handle will be */ /* written; */ /* */ /* Pointer to an int, in which the */ /* Plug-In task handle will be */ /* written, or 0 if the Object */ /* does not have an associated */ /* Plug-In or can't be found. */ /* */ /* Assumes: Either pointer may be NULL. */ /*************************************************/ static _kernel_oserror * object_get_object_plugin(browser_data * b, int object, unsigned int * plugin_instance, unsigned int * plugin_task) { /* Fill in zeros to start with */ if (plugin_instance) *plugin_instance = 0; if (plugin_task) *plugin_task = 0; /* Is this a valid object number? */ if (object < 0 || object >= b->nobjects) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Invalid object number %d passed to object_get_token_object_plugin (browser %08x, nobjects = %d)", object, (int) b, b->nobjects); return &erb; #endif return NULL; } /* If not associated with a Plug-In, exit */ if (!b->odata[object].isplugin) return NULL; /* Otherwise, return the details */ if (plugin_instance) *plugin_instance = b->odata[object].plugin_instance_handle; if (plugin_task) *plugin_task = b->odata[object].plugin_task_handle; /* Finished */ return NULL; } /*************************************************/ /* object_get_token_object_plugin() */ /* */ /* Returns details of any Plug-In associated */ /* with a given Object (referenced by token). */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to the token representing */ /* the Object; */ /* */ /* Pointer to an int, in which the */ /* Plug-In instance handle will be */ /* written; */ /* */ /* Pointer to an int, in which the */ /* Plug-In task handle will be */ /* written, or 0 if the Object */ /* does not have an associated */ /* Plug-In or can't be found. */ /* */ /* Assumes: Either pointer may be NULL. */ /*************************************************/ _kernel_oserror * object_get_token_object_plugin(browser_data * b, HStream * t, unsigned int * plugin_instance, unsigned int * plugin_task) { return object_get_object_plugin(b, object_get_token_object(b, t), plugin_instance, plugin_task); } /*************************************************/ /* object_set_object_plugin() */ /* */ /* Sets details of any Plug-In associated with */ /* a given Object (referenced by number). */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Number of the Object; */ /* */ /* Plug-In instance handle to set; */ /* */ /* Plug-In task handle to set. */ /* */ /* Assumes: Either pointer may be NULL. */ /*************************************************/ static _kernel_oserror * object_set_object_plugin(browser_data * b, int object, unsigned int plugin_instance, unsigned int plugin_task) { /* Is this a valid object number? */ if (object < 0 || object >= b->nobjects) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Invalid object number %d for passed to object_set_token_object_plugin (browser %08x, nobjects = %d)", object, (int) b, b->nobjects); return &erb; #endif return NULL; } /* If not associated with a Plug-In, exit */ if (!b->odata[object].isplugin) return NULL; /* Otherwise, set the details */ b->odata[object].plugin_instance_handle = plugin_instance; b->odata[object].plugin_task_handle = plugin_task; /* Finished */ return NULL; } /*************************************************/ /* object_set_token_object_plugin() */ /* */ /* Sets details of any Plug-In associated with */ /* a given Object (referenced by token). */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to the token representing */ /* the Object (usually have to */ /* remember this when the initial */ /* Message_PlugIn_Open is sent); */ /* */ /* Plug-In instance handle to set; */ /* */ /* Plug-In task handle to set. */ /* */ /* Assumes: Either pointer may be NULL. */ /*************************************************/ _kernel_oserror * object_set_token_object_plugin(browser_data * b, HStream * t, unsigned int plugin_instance, unsigned int plugin_task) { return object_set_object_plugin(b, object_get_token_object(b, t), plugin_instance, plugin_task); } /*************************************************/ /* object_redraw() */ /* */ /* Does a high level redraw of an Object, using */ /* an outline to show where the Object should be */ /* if it isn't plotted by some other method. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to a RedrawWindowBlock */ /* struct which holds information */ /* about the current redraw session; */ /* */ /* Address of the token representing */ /* the OBJECT, APPLET or EMBED tag; */ /* */ /* The X offset in window coords (so */ /* OS units) of the left hand edge */ /* of the Object; */ /* */ /* The Y offset in window coords (so */ /* OS units) of the bottom edge of */ /* the Object. */ /*************************************************/ _kernel_oserror * object_redraw(browser_data * b, WimpRedrawWindowBlock * r, HStream * token, int x, int y) { _kernel_oserror * e = NULL; int object = object_get_token_object(b, token); int plotted = 0; if (b->odata[object].isimage) { e = image_redraw(b, r, token, x, y); if (!e) plotted = 1; } if (!plotted) { /* Plot a placeholder */ BBox box; object_get_object_size(b, object, &box); box.xmin += x; box.ymin += y; box.xmax += x - box.xmin; box.ymax += y - box.ymin; box.xmin &= ~(wimpt_dx() - 1); box.ymin &= ~(wimpt_dy() - 1); redraw_draw_placeholder(b, r, &box, token, HtmlOBJECTstandby(token)); } return e; } /*************************************************/ /* object_token_is_image() */ /* */ /* Finds out whether an Object is acting as an */ /* an inline image or not. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the object; */ /* */ /* Pointer to the token representing */ /* the Object. */ /* */ /* Returns: 1 if the Object is acting as an */ /* inline image, else 0. */ /*************************************************/ int object_token_is_image(browser_data * b, HStream * t) { int object = object_get_token_object(b, t); if (object < 0 || object >= b->nobjects) return 0; else return !!b->odata[object].isimage; }