/* Copyright 1998 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 : ItemInfo.c */ /* */ /* Purpose: Functions relating to the Item */ /* Information window. */ /* */ /* Author : A.D.Hodgkinson */ /* */ /* History: 11-Mar-98: Created. */ /***************************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "swis.h" #include "kernel.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 "window.h" #include "svcprint.h" #include "Global.h" #include "MiscDefs.h" #include "Utils.h" #include "Browser.h" #include "Fetch.h" /* For ISLINK and ISOBJECT */ #include "Forms.h" #include "Images.h" #include "Menus.h" #include "Object.h" #include "Reformat.h" #include "Windows.h" #include "ItemInfo.h" /* Local statics */ static char * src_url = NULL; static char * dst_url = NULL; /* Static function prototypes */ static void iteminfo_info_not_available (ObjectId o, ComponentId c); static void iteminfo_info_none (ObjectId o, ComponentId c); static void iteminfo_store_source (ObjectId o, const char * source); static void iteminfo_store_destination (ObjectId o, const char * destination); static void iteminfo_send_to_keyboard_buffer (const char * s); static void iteminfo_fill_right (char * buffer, int buffer_size, const char * s); /*************************************************/ /* iteminfo_info_not_available() */ /* */ /* Fill in a display field with a string to show */ /* the information is not available. */ /* */ /* Parameters: Object ID of the object the */ /* display field lies in; */ /* */ /* Component ID of the display */ /* field. */ /*************************************************/ static void iteminfo_info_not_available(ObjectId o, ComponentId c) { displayfield_set_value(0, o, c, lookup_token("IINA:N/A",0,0)); return; } /*************************************************/ /* iteminfo_info_none() */ /* */ /* Fill in a display field with a string to show */ /* no information is available / relevant. */ /* */ /* Parameters: Object ID of the object the */ /* display field lies in; */ /* */ /* Component ID of the display */ /* field. */ /*************************************************/ static void iteminfo_info_none(ObjectId o, ComponentId c) { displayfield_set_value(0, o, c, lookup_token("IINone:(None)",0,0)); return; } /*************************************************/ /* iteminfo_store_source() */ /* */ /* Remember a URL as a source URL for some item, */ /* so the 'Export item' button can be used if */ /* present. Any URL already stored is discarded. */ /* */ /* Parameters: Object ID of the Item Information */ /* dialogue; */ /* */ /* Pointer to the URL to remember. */ /*************************************************/ static void iteminfo_store_source(ObjectId o, const char * source) { free(src_url); src_url = NULL; /* Remember the URL */ if (source && *source) { src_url = malloc(strlen(source) + 1); if (src_url) strcpy(src_url, source); } /* If we have a stored URL, ungrey the 'Export item' button, */ /* else grey it out. */ if (src_url) set_gadget_state(o, IIExportItem, 0); else set_gadget_state(o, IIExportItem, 1); return; } /*************************************************/ /* iteminfo_store_destination */ /* */ /* Remember a URL as a destination URL for some */ /* item, so the 'Follow link' button can be used */ /* if present. Any URL already stored is */ /* discarded. */ /* */ /* Parameters: Object ID of the Item Information */ /* dialogue; */ /* */ /* Pointer to the URL to remember. */ /*************************************************/ static void iteminfo_store_destination(ObjectId o, const char * destination) { free(dst_url); dst_url = NULL; /* Remember the URL */ if (destination && *destination) { dst_url = malloc(strlen(destination) + 1); if (dst_url) strcpy(dst_url, destination); } /* If we have a stored URL, ungrey the 'Follow Link' button, */ /* else grey it out. */ if (dst_url) set_gadget_state(o, IIFollowLink, 0); else set_gadget_state(o, IIFollowLink, 1); return; } /*************************************************/ /* iteminfo_send_to_keyboard_buffer() */ /* */ /* Little routine to send a stream of chars to */ /* the keyboard buffer. */ /* */ /* Parameters: Pointer to the string to send */ /* (terminator is not included). */ /*************************************************/ static void iteminfo_send_to_keyboard_buffer(const char * s) { if (!s) return; while (*s) { _swix(OS_Byte, _INR(0,2), 138, /* Insert char into buffer */ 0, /* Magic number alert - 0 = keyboard buffer */ *s++); /* Char to insert */ } } /*************************************************/ /* iteminfo_fill_right() */ /* */ /* Fills in the given buffer with either the */ /* whole of the given string, or, if it doesn't */ /* fit, the rightmost part of it. */ /* */ /* Parameters: Pointer to the buffer; */ /* */ /* Size of the buffer; */ /* */ /* Pointer to the string to fill in. */ /*************************************************/ static void iteminfo_fill_right(char * buffer, int buffer_size, const char * s) { int len; if (!s || !buffer || buffer_size < 1) return; len = strlen(s); if (len < buffer_size) strcpy(buffer, s); else strcpy(buffer, s + len - buffer_size + 1); return; } /*************************************************/ /* iteminfo_to_be_shown() */ /* */ /* Called before the Item Information window is */ /* shown - fills in the contents, based on the */ /* HStream and browser_data pointer returned by */ /* calls to menus_document_opened_over and */ /* menus_document_over_browser. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ int iteminfo_to_be_shown(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { ChkError(iteminfo_fill_in_contents(menus_document_over_browser(), menus_document_opened_over(), idb->self_id)); return 1; } /*************************************************/ /* iteminfo_follow_link() */ /* */ /* Called when the 'Export item' button is */ /* clicked on (or rather, the EIIFollowLink */ /* event is raised). */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ int iteminfo_follow_link(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { if (dst_url && *dst_url) { int ctrl; _swix(OS_Byte, _INR(0,1) | _OUT(1), 121, 129, &ctrl); /* If Control is not held down, follow the link */ if (!ctrl) { ChkError(windows_create_browser(dst_url, NULL, NULL, NULL, Windows_CreateBrowser_Normal)); } /* Otherwise, insert '<a href="<url>"></a>' into the keyboard buffer... */ else { char back[5]; iteminfo_send_to_keyboard_buffer("<a href=\""); iteminfo_send_to_keyboard_buffer(dst_url); iteminfo_send_to_keyboard_buffer("\"></a>"); /* Move cursor back before '</a>' */ back[0] = back[1] = back[2] = back[3] = 140; back[4] = 0; iteminfo_send_to_keyboard_buffer(back); } free(dst_url); dst_url = NULL; return 1; } else return 0; } /*************************************************/ /* iteminfo_export_item() */ /* */ /* Called when the 'Export item' button is */ /* clicked on (or rather, the EIIExportItem */ /* event is raised). */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ int iteminfo_export_item(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { if (src_url && *src_url) { int ctrl; _swix(OS_Byte, _INR(0,1) | _OUT(1), 121, 129, &ctrl); /* If Control is not held down, save the object */ if (!ctrl) { ChkError(windows_create_browser(src_url, NULL, NULL, NULL, Windows_CreateBrowser_SaveToFile)); } /* Otherwise, use the text in the display fields to construct */ /* part of what could be an IMG or OBJECT tag, or similar */ else { char number[32]; /* 'src="..."' */ iteminfo_send_to_keyboard_buffer("src=\""); iteminfo_send_to_keyboard_buffer(src_url); iteminfo_send_to_keyboard_buffer("\""); /* ' width="..."' */ if (!(displayfield_get_value(0, idb->self_id, IIActualSizeWidthDisplay, number, sizeof(number), NULL))) { number[sizeof(number) - 1] = 0; if (atoi(number)) { iteminfo_send_to_keyboard_buffer(" width=\""); iteminfo_send_to_keyboard_buffer(number); iteminfo_send_to_keyboard_buffer("\""); } } /* ' height="..."' */ if (!(displayfield_get_value(0, idb->self_id, IIActualSizeHeightDisplay, number, sizeof(number), NULL))) { number[sizeof(number) - 1] = 0; if (atoi(number)) { iteminfo_send_to_keyboard_buffer(" height=\""); iteminfo_send_to_keyboard_buffer(number); iteminfo_send_to_keyboard_buffer("\""); } } } free(src_url); src_url = NULL; return 1; } else return 0; } /*************************************************/ /* iteminfo_fill_in_contents() */ /* */ /* Fill in the Item Information window based on */ /* the given token. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the item; */ /* */ /* Pointer to the HStream to use as */ /* a source of information; */ /* */ /* Object ID of the Item Information */ /* dialogue to fill in. */ /*************************************************/ _kernel_oserror * iteminfo_fill_in_contents(browser_data * b, HStream * t, ObjectId o) { char url[Limits_ShortURL]; /* Invalidate the source and destination URLs */ iteminfo_store_source (o, NULL); iteminfo_store_destination (o, NULL); if (!t) { /* No token - so fill in fields with 'none' or 'not available' */ iteminfo_info_none(o, IIItemTypeDisplay); iteminfo_info_not_available(o, IILinkToDisplay); iteminfo_info_not_available(o, IIFetchedFromDisplay); iteminfo_info_not_available(o, IIActualSizeWidthDisplay); iteminfo_info_not_available(o, IIActualSizeHeightDisplay); iteminfo_info_not_available(o, IIScaledToWidthDisplay); iteminfo_info_not_available(o, IIScaledToHeightDisplay); } else { /* Deal with anchors at a generic level - other special */ /* types can override this if they really want to. */ if (ISLINK(t) && *t->anchor) { iteminfo_fill_right(url, sizeof(url), t->anchor); displayfield_set_value(0, o, IILinkToDisplay, url); iteminfo_store_destination(o, t->anchor); } else iteminfo_info_none(o, IILinkToDisplay); /* Now go through known token types */ if (t->tagno == TAG_INPUT || t->tagno == TAG_TEXTAREA || t->tagno == TAG_SELECT) { const char * sub; int post = 2; /* Forms item - for the 'link to', give the form submission URL, */ /* if available. */ sub = form_submission_information(b, t, &post); if (sub && *sub) { switch (post) { case 0: { iteminfo_fill_right(url, sizeof(url) - sizeof(" (GET)") + 1, sub); strcat(url, " (GET)"); } break; case 1: { iteminfo_fill_right(url, sizeof(url) - sizeof(" (POST)") + 1, sub); strcat(url, " (POST)"); } break; default: { iteminfo_fill_right(url, sizeof(url), sub); } break; } displayfield_set_value(0, o, IILinkToDisplay, url); iteminfo_store_destination(o, sub); } else iteminfo_info_none(o, IILinkToDisplay); /* INPUT TYPE=IMAGE is a special case. */ if (HtmlINPUTtype(t) == inputtype_IMAGE) { BBox size; char num[32]; displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IIFrmImg:Form element (image)",0,0)); /* Output the image source URL */ if (HtmlINPUTsrc(t)) { iteminfo_fill_right(url, sizeof(url), HtmlINPUTsrc(t)); displayfield_set_value(0, o, IIFetchedFromDisplay, url); iteminfo_store_source(o, HtmlINPUTsrc(t)); } else iteminfo_info_not_available(o, IIFetchedFromDisplay); /* Get the scaled size */ reformat_get_image_size(b, t, &size); sprintf(num, "%d", size.xmax - size.xmin); displayfield_set_value(0, o, IIScaledToWidthDisplay, num); sprintf(num, "%d", size.ymax - size.ymin); displayfield_set_value(0, o, IIScaledToHeightDisplay, num); /* Get the actual size */ image_get_token_actual_size(b, t, &size.xmin, &size.ymin); if (!size.xmin && !size.ymin) { iteminfo_info_not_available(o, IIActualSizeWidthDisplay); iteminfo_info_not_available(o, IIActualSizeHeightDisplay); } else { sprintf(num, "%d", size.xmin); displayfield_set_value(0, o, IIActualSizeWidthDisplay, num); sprintf(num, "%d", size.ymin); displayfield_set_value(0, o, IIActualSizeHeightDisplay, num); } } else { displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IIFrmGen:Form element (miscellaneous)",0,0)); goto do_unknown; } } else if (t->style & IMG) { BBox size; char num[32]; /* Output the image source URL */ if (t->src) { iteminfo_fill_right(url, sizeof(url), t->src); displayfield_set_value(0, o, IIFetchedFromDisplay, url); iteminfo_store_source(o, t->src); } else iteminfo_info_not_available(o, IIFetchedFromDisplay); /* Get the scaled size */ reformat_get_image_size(b, t, &size); sprintf(num, "%d", size.xmax - size.xmin); displayfield_set_value(0, o, IIScaledToWidthDisplay, num); sprintf(num, "%d", size.ymax - size.ymin); displayfield_set_value(0, o, IIScaledToHeightDisplay, num); /* Get the actual size */ image_get_token_actual_size(b, t, &size.xmin, &size.ymin); if (!size.xmin && !size.ymin) { iteminfo_info_not_available(o, IIActualSizeWidthDisplay); iteminfo_info_not_available(o, IIActualSizeHeightDisplay); displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IIImgNA:Image (size unknown)",0,0)); } else { sprintf(num, "%d", size.xmin); displayfield_set_value(0, o, IIActualSizeWidthDisplay, num); sprintf(num, "%d", size.ymin); displayfield_set_value(0, o, IIActualSizeHeightDisplay, num); displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IIImage:Image (size known)",0,0)); } } else if (ISOBJECT(t)) { const char * data = HtmlOBJECTdata(t); const char * current = browser_fetch_url(b); const char * newdata; /* For OBJECTs, need to jump a few hoops to get the source URL out */ if (!current) current = browser_current_url(b); if (current) { int known = 0; newdata = HtmlRelativiseURL(current, data, t); if (newdata) { if (object_token_is_image(b, t)) { BBox size; char num[32]; displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IIObjImg:Object (image)",0,0)); /* Output the object's source URL */ iteminfo_fill_right(url, sizeof(url), newdata); displayfield_set_value(0, o, IIFetchedFromDisplay, (char *) newdata); iteminfo_store_source(o, newdata); /* Will not need the relativised source URL from HtmlRelativiseURL */ /* again, so free it. If we forgot to do this, since it was */ /* allocated in the context of the token it'd get freed sooner or */ /* later with the rest of the stream. */ HtmlFree((void *) newdata); /* Get the scaled size */ object_get_token_object_size(b, t, &size); sprintf(num, "%d", size.xmax - size.xmin); displayfield_set_value(0, o, IIScaledToWidthDisplay, num); sprintf(num, "%d", size.ymax - size.ymin); displayfield_set_value(0, o, IIScaledToHeightDisplay, num); /* Get the actual size */ image_get_token_actual_size(b, t, &size.xmin, &size.ymin); if (!size.xmin && !size.ymin) { iteminfo_info_not_available(o, IIActualSizeWidthDisplay); iteminfo_info_not_available(o, IIActualSizeHeightDisplay); } else { sprintf(num, "%d", size.xmin); displayfield_set_value(0, o, IIActualSizeWidthDisplay, num); sprintf(num, "%d", size.ymin); displayfield_set_value(0, o, IIActualSizeHeightDisplay, num); } known = 1; /* Closure of 'if (object_is_image(...))' */ } /* Closure of 'if (newdata)' */ } /* If the object type was not dealt with (not known), use */ /* a generic string instead */ if (!known) { displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IIObjGen:Object (miscellaneous)",0,0)); goto do_unknown; } } } else if (t->tagno == 0 && (t->style & PCDATA)) { /* Some text */ if (ISLINK(t) && *t->anchor) { displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IITxtLnk:Piece of text (link)",0,0)); } else { displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IITxtPln:Piece of text (not a link)",0,0)); } goto do_unknown; } else { /* This isn't an item type we know about [yet] */ displayfield_set_value(0, o, IIItemTypeDisplay, lookup_token("IIUnknown:(Unknown)",0,0)); do_unknown: /* Jumped to for things which know the general */ /* item type, but can't fill in the details. */ /* Information is not available */ iteminfo_info_not_available(o, IIFetchedFromDisplay); iteminfo_info_not_available(o, IIActualSizeWidthDisplay); iteminfo_info_not_available(o, IIActualSizeHeightDisplay); iteminfo_info_not_available(o, IIScaledToWidthDisplay); iteminfo_info_not_available(o, IIScaledToHeightDisplay); } } return NULL; }