diff options
Diffstat (limited to 'src/htmlimage.c')
-rw-r--r-- | src/htmlimage.c | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/src/htmlimage.c b/src/htmlimage.c new file mode 100644 index 0000000..962ac5c --- /dev/null +++ b/src/htmlimage.c @@ -0,0 +1,225 @@ +/* +** Routines used for processing <IMG> markup +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <string.h> +#include <stdlib.h> +#include "htmlimage.h" + +/* +** Find the alignment for an image +*/ +int HtmlGetImageAlignment(HtmlElement *p){ + char *z; + int i; + int result; + + static struct { + char *zName; + int iValue; + } aligns[] = { + { "bottom", IMAGE_ALIGN_Bottom }, + { "baseline", IMAGE_ALIGN_Bottom }, + { "middle", IMAGE_ALIGN_Middle }, + { "top", IMAGE_ALIGN_Top }, + { "absbottom", IMAGE_ALIGN_AbsBottom }, + { "absmiddle", IMAGE_ALIGN_AbsMiddle }, + { "texttop", IMAGE_ALIGN_TextTop }, + { "left", IMAGE_ALIGN_Left }, + { "right", IMAGE_ALIGN_Right }, + }; + + z = HtmlMarkupArg(p, "align", 0); + result = IMAGE_ALIGN_Bottom; + if( z ){ + for(i=0; i<sizeof(aligns)/sizeof(aligns[0]); i++){ + if( stricmp(aligns[i].zName,z)==0 ){ + result = aligns[i].iValue; + TestPoint(0); + break; + }else{ + TestPoint(0); + } + } + }else{ + TestPoint(0); + } + return result; +} + +/* +** This routine is called when an image changes. If the size of the +** images changes, then we need to completely redo the layout. If +** only the appearance changes, then this works like an expose event. +*/ +static void ImageChangeProc( + ClientData clientData, /* Pointer to an HtmlImage structure */ + int x, /* Left edge of region that changed */ + int y, /* Top edge of region that changed */ + int w, /* Width of region that changes. Maybe 0 */ + int h, /* Height of region that changed. Maybe 0 */ + int newWidth, /* New width of the image */ + int newHeight /* New height of the image */ +){ + HtmlImage *pImage; + HtmlWidget *htmlPtr; + HtmlElement *pElem; + + pImage = (HtmlImage*)clientData; + htmlPtr = pImage->htmlPtr; + if( pImage->w!=newWidth || pImage->h!=newHeight ){ + /* We have to completely redo the layout after adjusting the size + ** of the images */ + for(pElem = pImage->pList; pElem; pElem = pElem->image.pNext){ + pElem->image.w = newWidth; + pElem->image.h = newHeight; + TestPoint(0); + } + htmlPtr->flags |= RELAYOUT; + pImage->w = newWidth; + pImage->h = newHeight; + HtmlRedrawEverything(htmlPtr); + }else{ + for(pElem = pImage->pList; pElem; pElem = pElem->image.pNext){ + pElem->image.redrawNeeded = 1; + } + htmlPtr->flags |= REDRAW_IMAGES; + HtmlScheduleRedraw(htmlPtr); + } +} + +/* +** Append all the arguments of the given markup to the given +** DString. +** +** Example: If the markup is <IMG SRC=image.gif ALT="hello!"> +** then the following text is appended to the DString: +** +** "src image.gif alt hello!" +** +** Notice how all attribute names are converted to lower case. +** This conversion happens in the parser. +*/ +void HtmlAppendArglist(Tcl_DString *str, HtmlElement *pElem){ + int i; + for(i=0; i+1<pElem->base.count; i+=2){ + char *z = pElem->markup.argv[i+1]; + Tcl_DStringAppendElement(str, pElem->markup.argv[i]); + Tcl_DStringAppendElement(str, z); + } +} + +/* +** Given an <IMG> markup, find or create an appropriate HtmlImage +** structure and return a pointer to that structure. NULL might +** be returned. +** +** This routine may invoke a callback procedure which could delete +** the HTML widget. Use HtmlLock() if necessary to preserve the +** widget structure. +*/ +HtmlImage *HtmlGetImage(HtmlWidget *htmlPtr, HtmlElement *p){ + char *zWidth; + char *zHeight; + char *zSrc; + char *zImageName; + HtmlImage *pImage; + int result; + Tcl_DString cmd; + int lenSrc, lenW, lenH; /* Lengths of various strings */ + + if( p->base.type!=Html_IMG ){ CANT_HAPPEN; return 0; } + if( htmlPtr->zGetImage==0 || htmlPtr->zGetImage[0]==0 ){ + TestPoint(0); + return 0; + } + zSrc = HtmlMarkupArg(p, "src", 0); + if( zSrc==0 ){ + return 0; + } + HtmlLock(htmlPtr); + zSrc = HtmlResolveUri(htmlPtr, zSrc); + if( HtmlUnlock(htmlPtr) || zSrc==0 ) return 0; + zWidth = HtmlMarkupArg(p, "width", ""); + zHeight = HtmlMarkupArg(p, "height", ""); + for(pImage=htmlPtr->imageList; pImage; pImage=pImage->pNext){ + if( strcmp(pImage->zUrl,zSrc)==0 + && strcmp(pImage->zWidth, zWidth)==0 + && strcmp(pImage->zHeight, zHeight)==0 ){ + HtmlFree(zSrc); + return pImage; + } + } + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zGetImage, -1); + Tcl_DStringAppendElement(&cmd,zSrc); + Tcl_DStringAppendElement(&cmd,zWidth); + Tcl_DStringAppendElement(&cmd,zHeight); + Tcl_DStringStartSublist(&cmd); + HtmlAppendArglist(&cmd, p); + Tcl_DStringEndSublist(&cmd); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( HtmlUnlock(htmlPtr) ){ + HtmlFree(zSrc); + } + zImageName = (char*)Tcl_GetStringResult(htmlPtr->interp); + lenSrc = strlen(zSrc); + lenW = strlen(zWidth); + lenH = strlen(zHeight); + pImage = HtmlAlloc( sizeof(HtmlImage) + lenSrc + lenW + lenH + 3 ); + memset(pImage,0,sizeof(HtmlImage)); + pImage->htmlPtr = htmlPtr; + pImage->zUrl = (char*)&pImage[1]; + strcpy(pImage->zUrl,zSrc); + HtmlFree(zSrc); + pImage->zWidth = &pImage->zUrl[lenSrc+1]; + strcpy(pImage->zWidth, zWidth); + pImage->zHeight = &pImage->zWidth[lenW+1]; + strcpy(pImage->zHeight, zHeight); + pImage->w = 0; + pImage->h = 0; + if( result==TCL_OK ){ + pImage->image = Tk_GetImage(htmlPtr->interp, htmlPtr->clipwin, + zImageName, ImageChangeProc, pImage); + TestPoint(0); + }else{ + Tcl_AddErrorInfo(htmlPtr->interp, + "\n (\"-imagecommand\" command executed by html widget)"); + Tcl_BackgroundError(htmlPtr->interp); + pImage->image = 0; + TestPoint(0); + } + if( pImage->image==0 ){ + HtmlFree((char*)pImage); + TestPoint(0); + return 0; + } + pImage->pNext = htmlPtr->imageList; + htmlPtr->imageList = pImage; + TestPoint(0); + Tcl_ResetResult(htmlPtr->interp); + return pImage; +} |