diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2019-01-07 20:02:26 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2019-01-07 20:02:26 (GMT) |
commit | dd7ebc578d780f789cf3a15f249c8a874faf79e3 (patch) | |
tree | fb96917e1f49ca7bcef7efc1107c1306f604a471 /tkhtml1/generic/htmlwidget.c | |
parent | 40254c18e6e39a5d7b83ec6bebf5506851309eb7 (diff) | |
download | blt-dd7ebc578d780f789cf3a15f249c8a874faf79e3.zip blt-dd7ebc578d780f789cf3a15f249c8a874faf79e3.tar.gz blt-dd7ebc578d780f789cf3a15f249c8a874faf79e3.tar.bz2 |
update TEA 3.13
Diffstat (limited to 'tkhtml1/generic/htmlwidget.c')
-rw-r--r-- | tkhtml1/generic/htmlwidget.c | 2043 |
1 files changed, 0 insertions, 2043 deletions
diff --git a/tkhtml1/generic/htmlwidget.c b/tkhtml1/generic/htmlwidget.c deleted file mode 100644 index 3d6e632..0000000 --- a/tkhtml1/generic/htmlwidget.c +++ /dev/null @@ -1,2043 +0,0 @@ -/* -** The main routine for the HTML widget for Tcl/Tk -** -** 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 <ctype.h> -#include <stdlib.h> -#include <string.h> -#include "htmlwidget.h" -/* -#ifdef USE_TK_STUBS -# include <tkIntXlibDecls.h> -#endif -*/ -/* -** This global variable is used for tracing the operation of -** the Html formatter. -*/ -int HtmlTraceMask = 0; - -#ifdef __WIN32__ -# define DEF_FRAME_BG_COLOR "SystemButtonFace" -# define DEF_FRAME_BG_MONO "White" -# define DEF_FRAME_CURSOR "" -# define DEF_BUTTON_FG "SystemButtonText" -# define DEF_BUTTON_HIGHLIGHT_BG "SystemButtonFace" -# define DEF_BUTTON_HIGHLIGHT "SystemWindowFrame" -#else -# define DEF_FRAME_BG_COLOR "#d9d9d9" -# define DEF_FRAME_BG_MONO "White" -# define DEF_FRAME_CURSOR "" -# define DEF_BUTTON_FG "Black" -# define DEF_BUTTON_HIGHLIGHT_BG "#d9d9d9" -# define DEF_BUTTON_HIGHLIGHT "Black" -#endif - -/* -** Information used for argv parsing. -*/ -static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_STRING, "-appletcommand", "appletCommand", "HtmlCallback", - DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zAppletCommand), 0}, - {TK_CONFIG_BORDER, "-background", "background", "Background", - DEF_HTML_BG_COLOR, Tk_Offset(HtmlWidget, border), - TK_CONFIG_COLOR_ONLY}, - {TK_CONFIG_BORDER, "-background", "background", "Background", - DEF_HTML_BG_MONO, Tk_Offset(HtmlWidget, border), - TK_CONFIG_MONO_ONLY}, - {TK_CONFIG_STRING, "-base", "base", "Base", - "", Tk_Offset(HtmlWidget, zBase), 0}, - {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL, - (char *) NULL, 0, 0}, - {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL, - (char *) NULL, 0, 0}, - {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_HTML_BORDER_WIDTH, Tk_Offset(HtmlWidget, borderWidth), 0}, - {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", - DEF_HTML_CURSOR, Tk_Offset(HtmlWidget, cursor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection","ExportSelection", - DEF_HTML_EXPORT_SEL, Tk_Offset(HtmlWidget, exportSelection), 0}, - {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, 0}, - {TK_CONFIG_STRING, "-fontcommand", "fontCommand", "FontCommand", - DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zFontCommand), 0}, - {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground", - DEF_HTML_FG, Tk_Offset(HtmlWidget, fgColor), 0}, - {TK_CONFIG_STRING, "-formcommand", "formlCommand", "HtmlCallback", - DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zFormCommand), 0}, - {TK_CONFIG_STRING, "-framecommand", "frameCommand", "HtmlCallback", - DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zFrameCommand), 0}, - {TK_CONFIG_PIXELS, "-height", "height", "Height", - DEF_HTML_HEIGHT, Tk_Offset(HtmlWidget, height), 0}, - {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", - "HighlightBackground", DEF_HTML_HIGHLIGHT_BG, - Tk_Offset(HtmlWidget, highlightBgColorPtr), 0}, - {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_HTML_HIGHLIGHT, Tk_Offset(HtmlWidget, highlightColorPtr), 0}, - {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", - "HighlightThickness", - DEF_HTML_HIGHLIGHT_WIDTH, Tk_Offset(HtmlWidget, highlightWidth), 0}, - {TK_CONFIG_STRING, "-hyperlinkcommand", "hyperlinkCommand", "HtmlCallback", - DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zHyperlinkCommand), 0}, - {TK_CONFIG_STRING, "-imagecommand", "imageCommand", "HtmlCallback", - DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zGetImage), 0}, - {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime", - DEF_HTML_INSERT_OFF_TIME, Tk_Offset(HtmlWidget, insOffTime), 0}, - {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime", - DEF_HTML_INSERT_ON_TIME, Tk_Offset(HtmlWidget, insOnTime), 0}, - {TK_CONFIG_STRING, "-isvisitedcommand", "isVisitedCommand", "HtmlCallback", - DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zIsVisited), 0}, - {TK_CONFIG_PIXELS, "-padx", "padX", "Pad", - DEF_HTML_PADX, Tk_Offset(HtmlWidget, padx), 0}, - {TK_CONFIG_PIXELS, "-pady", "padY", "Pad", - DEF_HTML_PADY, Tk_Offset(HtmlWidget, pady), 0}, - {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", - DEF_HTML_RELIEF, Tk_Offset(HtmlWidget, relief), 0}, - {TK_CONFIG_STRING, "-resolvercommand", "resolverCommand", "HtmlCallback", - DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zResolverCommand), 0}, - {TK_CONFIG_RELIEF, "-rulerelief", "ruleRelief","RuleRelief", - "sunken", Tk_Offset(HtmlWidget, ruleRelief), 0}, - {TK_CONFIG_STRING, "-scriptcommand", "scriptCommand", "HtmlCallback", - "", Tk_Offset(HtmlWidget, zScriptCommand), 0}, - {TK_CONFIG_COLOR, "-selectioncolor", "background", "Background", - DEF_HTML_SELECTION_COLOR, Tk_Offset(HtmlWidget, selectionColor), 0}, - {TK_CONFIG_RELIEF, "-tablerelief", "tableRelief","TableRelief", - "raised", Tk_Offset(HtmlWidget, tableRelief), 0}, - {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_HTML_TAKE_FOCUS, Tk_Offset(HtmlWidget, takeFocus), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-unvisitedcolor", "foreground", "Foreground", - DEF_HTML_UNVISITED, Tk_Offset(HtmlWidget, newLinkColor), 0}, - {TK_CONFIG_BOOLEAN, "-underlinehyperlinks", "underlineHyperlinks", - "UnderlineHyperlinks", "1", Tk_Offset(HtmlWidget, underlineLinks), 0}, - {TK_CONFIG_COLOR, "-visitedcolor", "foreground", "Foreground", - DEF_HTML_VISITED, Tk_Offset(HtmlWidget, oldLinkColor), 0}, - {TK_CONFIG_PIXELS, "-width", "width", "Width", - DEF_HTML_WIDTH, Tk_Offset(HtmlWidget, width), 0}, - {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - DEF_HTML_SCROLL_COMMAND, Tk_Offset(HtmlWidget, xScrollCmd), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - DEF_HTML_SCROLL_COMMAND, Tk_Offset(HtmlWidget, yScrollCmd), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} -}; - -/* -** Get a copy of the config specs. -*/ -Tk_ConfigSpec *HtmlConfigSpec(void){ - return configSpecs; -} - -/* -** Find the width of the usable drawing area in pixels. If the window isn't -** mapped, use the size requested by the user. -** -** The usable drawing area is the area available for displaying rendered -** HTML. The usable drawing area does not include the 3D border or the -** padx and pady boundry within the 3D border. The usable drawing area -** is the size of the clipping window. -*/ -int HtmlUsableWidth(HtmlWidget *htmlPtr){ - int w; - Tk_Window tkwin = htmlPtr->tkwin; - if( tkwin && Tk_IsMapped(tkwin) ){ - w = Tk_Width(tkwin) - 2*(htmlPtr->padx + htmlPtr->inset); - TestPoint(0); - }else{ - w = htmlPtr->width; - TestPoint(0); - } - return w; -} - -/* -** Find the height of the usable drawing area in pixels. If the window isn't -** mapped, use the size requested by the user. -** -** The usable drawing area is the area available for displaying rendered -** HTML. The usable drawing area does not include the 3D border or the -** padx and pady boundry within the 3D border. The usable drawing area -** is the size of the clipping window. -*/ -int HtmlUsableHeight(HtmlWidget *htmlPtr){ - int h; - Tk_Window tkwin = htmlPtr->tkwin; - if( tkwin && Tk_IsMapped(tkwin) ){ - h = Tk_Height(tkwin) - 2*(htmlPtr->pady + htmlPtr->inset); - TestPoint(0); - }else{ - h = htmlPtr->height; - TestPoint(0); - } - return h; -} - -/* -** Compute a pair of floating point numbers that describe the current -** vertical scroll position. The first number is the fraction of -** the document that is off the top of the visible region and the second -** number is the fraction that is beyond the end of the visible region. -*/ -void HtmlComputeVerticalPosition( - HtmlWidget *htmlPtr, - char *buf /* Write the two floating point values here */ -){ - int actual; /* Size of the viewing area */ - double frac1, frac2; - - actual = HtmlUsableHeight(htmlPtr); - if( htmlPtr->maxY <= 0 ){ - frac1 = 0.0; - frac2 = 1.0; - TestPoint(0); - }else{ - frac1 = (double)htmlPtr->yOffset/(double)htmlPtr->maxY; - if( frac1 > 1.0 ){ - frac1 = 1.0; - TestPoint(0); - }else if( frac1 < 0.0 ){ - frac1 = 0.0; - TestPoint(0); - } - frac2 = (double)(htmlPtr->yOffset+actual)/(double)htmlPtr->maxY; - if( frac2 > 1.0 ){ - frac2 = 1.0; - TestPoint(0); - }else if( frac2 < 0.0 ){ - frac2 = 0.0; - TestPoint(0); - } - } - sprintf(buf,"%g %g",frac1, frac2); -} - -/* -** Do the same thing for the horizontal direction -*/ -void HtmlComputeHorizontalPosition( - HtmlWidget *htmlPtr, - char *buf /* Write the two floating point values here */ -){ - int actual; /* Size of the viewing area */ - double frac1, frac2; - - actual = HtmlUsableWidth(htmlPtr); - if( htmlPtr->maxX <= 0 ){ - frac1 = 0.0; - frac2 = 1.0; - TestPoint(0); - }else{ - frac1 = (double)htmlPtr->xOffset/(double)htmlPtr->maxX; - if( frac1 > 1.0 ){ - frac1 = 1.0; - TestPoint(0); - }else if( frac1 < 0.0 ){ - frac1 = 0.0; - TestPoint(0); - } - frac2 = (double)(htmlPtr->xOffset+actual)/(double)htmlPtr->maxX; - if( frac2 > 1.0 ){ - frac2 = 1.0; - TestPoint(0); - }else if( frac2 < 0.0 ){ - frac2 = 0.0; - TestPoint(0); - } - } - sprintf(buf,"%g %g",frac1, frac2); -} - -/* -** Clear the cache of GCs -*/ -static void ClearGcCache(HtmlWidget *htmlPtr){ - int i; - for(i=0; i<N_CACHE_GC; i++){ - if( htmlPtr->aGcCache[i].index ){ - Tk_FreeGC(htmlPtr->display, htmlPtr->aGcCache[i].gc); - htmlPtr->aGcCache[i].index = 0; - TestPoint(0); - }else{ - TestPoint(0); - } - } -} - - -/* -** This routine is called when the widget command is deleted. If the -** widget isn't already in the process of being destroyed, this command -** starts that process rolling. -** -** This routine can be called in two ways. -** -** (1) The window is destroyed, which causes the command to be deleted. -** In this case, we don't have to do anything. -** -** (2) The command only is deleted (ex: "rename .html {}"). In that -** case we need to destroy the window. -*/ -static void HtmlCmdDeletedProc(ClientData clientData){ - HtmlWidget *htmlPtr = (HtmlWidget*) clientData; - if (htmlPtr != NULL && htmlPtr->tkwin!=NULL ) { - Tk_Window tkwin = htmlPtr->tkwin; - htmlPtr->tkwin = NULL; - Tk_DestroyWindow(tkwin); - } -} - -/* -** Reset the main layout context in the main widget. This happens -** before we redo the layout, or just before deleting the widget. -*/ -static void ResetLayoutContext(HtmlWidget *htmlPtr){ - htmlPtr->layoutContext.headRoom = 0; - htmlPtr->layoutContext.top = 0; - htmlPtr->layoutContext.bottom = 0; - HtmlClearMarginStack(&htmlPtr->layoutContext.leftMargin); - HtmlClearMarginStack(&htmlPtr->layoutContext.rightMargin); -} - -/* -** This routine is invoked in order to redraw all or part of the HTML -** widget. This might happen because the display has changed, or in -** response to an expose event. In all cases, though, this routine -** is called by an idle callback. -*/ -static void HtmlRedrawCallback(ClientData clientData){ - HtmlWidget *htmlPtr = (HtmlWidget*)clientData; - Tk_Window tkwin = htmlPtr->tkwin; - Tk_Window clipwin = htmlPtr->clipwin; - Pixmap pixmap; /* The buffer on which to render HTML */ - int x, y, w, h; /* Virtual canvas coordinates of area to draw */ - int hw; /* highlight thickness */ - int insetX, insetY; /* Total highlight thickness, border width and - ** padx/y */ - int clipwinH, clipwinW; /* Width and height of the clipping window */ - HtmlBlock *pBlock; /* For looping over blocks to be drawn */ - int redoSelection = 0; /* True to recompute the selection */ - - /* - ** Don't bother doing anything if the widget is in the process of - ** being destroyed. - */ - if( tkwin==0 ){ - goto redrawExit; - } - - /* - ** Recompute the layout, if necessary or requested. - ** - ** Calling HtmlLayout() is tricky because HtmlLayout() may invoke one - ** or more callbacks (thru the "-imagecommand" callback, for instance) - ** and these callbacks could, in theory, do nasty things like delete - ** or unmap this widget. So we have to take precautions: - ** - ** * Don't remove the REDRAW_PENDING flag until after HtmlLayout() - ** has been called, to prevent a recursive call to HtmlRedrawCallback(). - ** - ** * Call HtmlLock() on the htmlPtr structure to prevent it from - ** being deleted out from under us. - ** - */ - if( (htmlPtr->flags & RESIZE_ELEMENTS)!=0 - && (htmlPtr->flags & STYLER_RUNNING)==0 ){ - HtmlImage *pImage; - for(pImage=htmlPtr->imageList; pImage; pImage=pImage->pNext){ - pImage->pList = 0; - } - htmlPtr->lastSized = 0; - htmlPtr->flags &= ~RESIZE_ELEMENTS; - htmlPtr->flags |= RELAYOUT; - } - - /* We used to make a distinction between RELAYOUT and EXTEND_LAYOUT. - ** RELAYOUT would be used when the widget was resized, but the - ** less compute-intensive EXTEND_LAYOUT would be used when new - ** text was appended. - ** - ** Unfortunately, EXTEND_LAYOUT has some problem that arise when - ** tables are used. The quick fix is to make an EXTEND_LAYOUT do - ** a complete RELAYOUT. Someday, we need to fix EXTEND_LAYOUT so - ** that it works right... - */ - if( (htmlPtr->flags & (RELAYOUT|EXTEND_LAYOUT))!=0 - && (htmlPtr->flags & STYLER_RUNNING)==0 ){ - htmlPtr->nextPlaced = 0; - htmlPtr->nInput = 0; - htmlPtr->varId = 0; - htmlPtr->maxX = 0; - htmlPtr->maxY = 0; - ResetLayoutContext(htmlPtr); - htmlPtr->firstBlock = 0; - htmlPtr->lastBlock = 0; - redoSelection = 1; - htmlPtr->flags &= ~RELAYOUT; - htmlPtr->flags |= HSCROLL | VSCROLL | REDRAW_TEXT | EXTEND_LAYOUT; - } - if( (htmlPtr->flags & EXTEND_LAYOUT) && htmlPtr->pFirst!=0 ){ - HtmlLock(htmlPtr); - HtmlLayout(htmlPtr); - if( HtmlUnlock(htmlPtr) ) goto redrawExit; - tkwin = htmlPtr->tkwin; - htmlPtr->flags &= ~EXTEND_LAYOUT; - HtmlFormBlocks(htmlPtr); - HtmlMapControls(htmlPtr); - if( redoSelection && htmlPtr->selBegin.p && htmlPtr->selEnd.p ){ - HtmlUpdateSelection(htmlPtr,1); - HtmlUpdateInsert(htmlPtr); - } - } - htmlPtr->flags &= ~REDRAW_PENDING; - - /* No need to do any actual drawing if we aren't mapped - */ - if( !Tk_IsMapped(tkwin) ){ - goto redrawExit; - } - - /* Redraw the scrollbars. Take care here, since the scrollbar - ** update command could (in theory) delete the html widget, or - ** even the whole interpreter. Preserve critical data structures, - ** and check to see if we are still alive before continuing. - */ - if( (htmlPtr->flags & (HSCROLL|VSCROLL)) != 0 ){ - Tcl_Interp *interp = htmlPtr->interp; - int result; - char buf[200]; - - if( (htmlPtr->flags & HSCROLL)!=0 ){ - if( htmlPtr->xScrollCmd && htmlPtr->xScrollCmd[0] ){ - HtmlComputeHorizontalPosition(htmlPtr,buf); - HtmlLock(htmlPtr); - result = Tcl_VarEval(interp, htmlPtr->xScrollCmd, " ", buf, NULL); - if( HtmlUnlock(htmlPtr) ) goto redrawExit; - if (result != TCL_OK) { - Tcl_AddErrorInfo(interp, - "\n (horizontal scrolling command executed by html widget)"); - Tcl_BackgroundError(interp); - TestPoint(0); - } - } - htmlPtr->flags &= ~HSCROLL; - } - if( (htmlPtr->flags & VSCROLL)!=0 && tkwin && Tk_IsMapped(tkwin) ){ - if( htmlPtr->yScrollCmd && htmlPtr->yScrollCmd[0] ){ - Tcl_Interp *interp = htmlPtr->interp; - int result; - char buf[200]; - HtmlComputeVerticalPosition(htmlPtr,buf); - HtmlLock(htmlPtr); - result = Tcl_VarEval(interp, htmlPtr->yScrollCmd, " ", buf, NULL); - if( HtmlUnlock(htmlPtr) ) goto redrawExit; - if (result != TCL_OK) { - Tcl_AddErrorInfo(interp, - "\n (horizontal scrolling command executed by html widget)"); - Tcl_BackgroundError(interp); - TestPoint(0); - } - } - htmlPtr->flags &= ~VSCROLL; - } - tkwin = htmlPtr->tkwin; - if( tkwin==0 || !Tk_IsMapped(tkwin) ){ goto redrawExit; } - if( htmlPtr->flags & REDRAW_PENDING ){ return; } - clipwin = htmlPtr->clipwin; - if( clipwin==0 ){ TestPoint(0); goto redrawExit; } - } - - /* Redraw the focus highlight, if requested */ - hw = htmlPtr->highlightWidth; - if( htmlPtr->flags & REDRAW_FOCUS ){ - if( hw>0 ){ - GC gc; - Tk_Window tkwin = htmlPtr->tkwin; - - if( htmlPtr->flags & GOT_FOCUS ){ - gc = Tk_GCForColor(htmlPtr->highlightColorPtr, Tk_WindowId(tkwin)); - TestPoint(0); - }else{ - gc = Tk_GCForColor(htmlPtr->highlightBgColorPtr, Tk_WindowId(tkwin)); - TestPoint(0); - } - Tk_DrawFocusHighlight(tkwin, gc, hw, Tk_WindowId(tkwin)); - } - htmlPtr->flags &= ~REDRAW_FOCUS; - } - - /* Draw the borders around the parameter of the window. This is - ** drawn directly -- it is not double buffered. - */ - if( htmlPtr->flags & REDRAW_BORDER ){ - htmlPtr->flags &= ~REDRAW_BORDER; - Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), htmlPtr->border, - hw, /* x */ - hw, /* y */ - Tk_Width(tkwin) - 2*hw, /* width */ - Tk_Height(tkwin) - 2*hw, /* height */ - htmlPtr->borderWidth, htmlPtr->relief); - } - - /* - ** If the styler is in a callback, unmap the clipping window and - ** abort further processing. - */ - if( htmlPtr->flags & STYLER_RUNNING ){ - if( Tk_IsMapped(clipwin) ){ - Tk_UnmapWindow(clipwin); - } - goto earlyOut; - } - - /* - ** If we don't have a clipping window, then something is seriously - ** wrong. We might as well give up. - */ - if( clipwin==NULL ){ TestPoint(0); goto earlyOut; } - - /* Resize, reposition and map the clipping window, if necessary */ - insetX = htmlPtr->padx + htmlPtr->inset; - insetY = htmlPtr->pady + htmlPtr->inset; - if( htmlPtr->flags & RESIZE_CLIPWIN ){ - int h, w; - Tk_MoveResizeWindow(clipwin, insetX, insetY, - htmlPtr->realWidth - 2*insetX, - htmlPtr->realHeight - 2*insetY); - if( !Tk_IsMapped(clipwin) ){ - Tk_MapWindow(clipwin); - } - h = htmlPtr->realHeight - 2*insetY; - if( htmlPtr->yOffset + h > htmlPtr->maxY ){ - htmlPtr->yOffset = htmlPtr->maxY - h; - } - if( htmlPtr->yOffset < 0 ){ - htmlPtr->yOffset = 0; - } - w = htmlPtr->realWidth - 2*insetX; - if( htmlPtr->xOffset + h > htmlPtr->maxX ){ - htmlPtr->xOffset = htmlPtr->maxX - w; - } - if( htmlPtr->xOffset < 0 ){ - htmlPtr->xOffset = 0; - } - htmlPtr->flags &= ~RESIZE_CLIPWIN; - } - HtmlMapControls(htmlPtr); - - /* - ** Compute the virtual canvas coordinates corresponding to the - ** dirty region of the clipping window. - */ - clipwinW = Tk_Width(clipwin); - clipwinH = Tk_Height(clipwin); - if( htmlPtr->flags & REDRAW_TEXT ){ - w = clipwinW; - h = clipwinH; - x = htmlPtr->xOffset; - y = htmlPtr->yOffset; - htmlPtr->dirtyLeft = 0; - htmlPtr->dirtyTop = 0; - htmlPtr->flags &= ~REDRAW_TEXT; - }else{ - if( htmlPtr->dirtyLeft < 0 ){ - htmlPtr->dirtyLeft = 0; - TestPoint(0); - } - if( htmlPtr->dirtyRight > clipwinW ){ - htmlPtr->dirtyRight = clipwinW; - TestPoint(0); - } - if( htmlPtr->dirtyTop < 0 ){ - htmlPtr->dirtyTop = 0; - TestPoint(0); - } - if( htmlPtr->dirtyBottom > clipwinH ){ - htmlPtr->dirtyBottom = clipwinH; - TestPoint(0); - } - w = htmlPtr->dirtyRight - htmlPtr->dirtyLeft; - h = htmlPtr->dirtyBottom - htmlPtr->dirtyTop; - x = htmlPtr->xOffset + htmlPtr->dirtyLeft; - y = htmlPtr->yOffset + htmlPtr->dirtyTop; - } - - /* Skip the rest of the drawing process if the area to be refreshed is - ** less than zero */ - if( w>0 && h>0 ){ - Display *display = htmlPtr->display; - int dead; - GC gcBg; - XRectangle xrec; - /* printf("Redraw %dx%d at %d,%d\n", w, h, x, y); */ - - /* Allocate and clear a pixmap upon which to draw */ - gcBg = HtmlGetGC(htmlPtr, COLOR_Background, FONT_Any); - pixmap = Tk_GetPixmap(display, Tk_WindowId(clipwin),w,h,Tk_Depth(clipwin)); - xrec.x = 0; - xrec.y = 0; - xrec.width = w; - xrec.height = h; - XFillRectangles(display, pixmap, gcBg, &xrec, 1); - - /* Render all visible HTML onto the pixmap */ - HtmlLock(htmlPtr); - for(pBlock=htmlPtr->firstBlock; pBlock; pBlock=pBlock->pNext){ - if( pBlock->top <= y+h && pBlock->bottom >= y - && pBlock->left <= x+w && pBlock->right >= x ){ - HtmlBlockDraw(htmlPtr,pBlock,pixmap,x,y,w,h); - if( htmlPtr->tkwin==0 ) break; - } - } - dead = HtmlUnlock(htmlPtr); - - /* Finally, copy the pixmap onto the window and delete the pixmap */ - if( !dead ){ - XCopyArea(display, pixmap, Tk_WindowId(clipwin), - gcBg, 0, 0, w, h, htmlPtr->dirtyLeft, htmlPtr->dirtyTop); - } - Tk_FreePixmap(display, pixmap); - if( dead ) goto redrawExit; - /* XFlush(display); */ - } - - /* Redraw images, if requested */ - if( htmlPtr->flags & REDRAW_IMAGES ){ - HtmlImage *pImage; - HtmlElement *pElem; - int top, bottom, left, right; /* Coordinates of the clipping window */ - int imageTop; /* Top edge of image */ - - top = htmlPtr->yOffset; - bottom = top + HtmlUsableHeight(htmlPtr); - left = htmlPtr->xOffset; - right = left + HtmlUsableWidth(htmlPtr); - for(pImage = htmlPtr->imageList; pImage; pImage=pImage->pNext){ - for(pElem = pImage->pList; pElem; pElem=pElem->image.pNext){ - if( pElem->image.redrawNeeded==0 ) continue; - imageTop = pElem->image.y - pElem->image.ascent; - if( imageTop > bottom - || imageTop + pElem->image.h < top - || pElem->image.x > right - || pElem->image.x + pElem->image.w < left ){ - TestPoint(0); - continue; - } - HtmlDrawImage(pElem, Tk_WindowId(htmlPtr->clipwin), - left, top, right, bottom); - } - } - htmlPtr->flags &= ~REDRAW_IMAGES; - } - - /* Set the dirty region to the empty set. */ - earlyOut: - htmlPtr->dirtyTop = LARGE_NUMBER; - htmlPtr->dirtyLeft = LARGE_NUMBER; - htmlPtr->dirtyBottom = 0; - htmlPtr->dirtyRight = 0; - redrawExit: - return; -} - -/* -** Make sure that a call to the HtmlRedrawCallback() routine has been -** queued. -*/ -void HtmlScheduleRedraw(HtmlWidget *htmlPtr){ - if( (htmlPtr->flags & REDRAW_PENDING)==0 - && htmlPtr->tkwin!=0 - && Tk_IsMapped(htmlPtr->tkwin) - ){ - Tcl_DoWhenIdle(HtmlRedrawCallback, (ClientData)htmlPtr); - htmlPtr->flags |= REDRAW_PENDING; - } -} - -/* -** If any part of the screen needs to be redrawn, Then call this routine -** with the values of a box (in window coordinates) that needs to be -** redrawn. This routine will make sure an idle callback is scheduled -** to do the redraw. -** -** The box coordinates are relative to the clipping window (clipwin), -** not the main window (tkwin). -*/ -void HtmlRedrawArea( - HtmlWidget *htmlPtr, /* The widget to be redrawn */ - int left, int top, /* Top left corner of area to redraw */ - int right, int bottom /* bottom right corner of area to redraw */ -){ - if( bottom < 0 ){ TestPoint(0); return; } - if( top > htmlPtr->realHeight ){ TestPoint(0); return; } - if( right < 0 ){ TestPoint(0); return; } - if( left > htmlPtr->realWidth ){ TestPoint(0); return; } - if( htmlPtr->dirtyTop > top ){ htmlPtr->dirtyTop = top; TestPoint(0);} - if( htmlPtr->dirtyLeft > left ){ htmlPtr->dirtyLeft = left; TestPoint(0);} - if( htmlPtr->dirtyBottom < bottom ){ - htmlPtr->dirtyBottom = bottom; - TestPoint(0); - } - if( htmlPtr->dirtyRight < right ){ htmlPtr->dirtyRight = right; TestPoint(0);} - HtmlScheduleRedraw(htmlPtr); - TestPoint(0); -} - -/* Redraw the HtmlBlock given. -*/ -void HtmlRedrawBlock(HtmlWidget *htmlPtr, HtmlBlock *p){ - if( p ){ - HtmlRedrawArea(htmlPtr, - p->left - htmlPtr->xOffset, - p->top - htmlPtr->yOffset, - p->right - htmlPtr->xOffset + 1, - p->bottom - htmlPtr->yOffset - ); - TestPoint(0); - }else{ - TestPoint(0); - } -} - -/* -** Call this routine to force the entire widget to be redrawn. -*/ -void HtmlRedrawEverything(HtmlWidget *htmlPtr){ - htmlPtr->flags |= REDRAW_FOCUS | REDRAW_TEXT | REDRAW_BORDER; - HtmlScheduleRedraw(htmlPtr); - TestPoint(0); -} - -/* -** Do the redrawing right now. Don't wait. -*/ -#if 0 /* NOT_USED */ -static void HtmlRedrawPush(HtmlWidget *htmlPtr){ - if( htmlPtr->flags & REDRAW_PENDING ){ - Tcl_CancelIdleCall(HtmlRedrawCallback, (ClientData)htmlPtr); - TestPoint(0); - }else{ - TestPoint(0); - } - HtmlRedrawCallback( (ClientData)htmlPtr ); -} -#endif - -/* -** Call this routine to cause all of the rendered HTML at the -** virtual canvas coordinate of Y and beyond to be redrawn. -*/ -void HtmlRedrawText(HtmlWidget *htmlPtr, int y){ - int yOffset; /* Top-most visible canvas coordinate */ - int clipHeight; /* Height of the clipping window */ - - yOffset = htmlPtr->yOffset; - clipHeight = HtmlUsableHeight(htmlPtr); - y -= yOffset; - if( y < clipHeight ){ - HtmlRedrawArea(htmlPtr, 0, y, LARGE_NUMBER, clipHeight); - TestPoint(0); - }else{ - TestPoint(0); - } -} - -/* -** Recalculate the preferred size of the html widget and pass this -** along to the geometry manager. -*/ -static void HtmlRecomputeGeometry(HtmlWidget *htmlPtr){ - int w, h; /* Total width and height of the widget */ - - htmlPtr->inset = htmlPtr->highlightWidth + htmlPtr->borderWidth; - w = htmlPtr->width + 2*(htmlPtr->padx + htmlPtr->inset); - h = htmlPtr->height + 2*(htmlPtr->pady + htmlPtr->inset); - Tk_GeometryRequest(htmlPtr->tkwin, w, h); - Tk_SetInternalBorder(htmlPtr->tkwin, htmlPtr->inset); - TestPoint(0); -} - -/* -** This routine is called in order to process a "configure" subcommand -** on the given html widget. -*/ -int ConfigureHtmlWidget( - Tcl_Interp *interp, /* Write error message to this interpreter */ - HtmlWidget *htmlPtr, /* The Html widget to be configured */ - int argc, /* Number of configuration arguments */ - const char **argv, /* Text of configuration arguments */ - int flags, /* Configuration flags */ - int realign /* Always do a redraw if set */ -){ - int rc; - int i; - int redraw = realign; /* True if a redraw is required. */ - - /* Scan thru the configuration options to see if we need to redraw - ** the widget. - */ - for(i=0; redraw==0 && i<argc; i+=2){ - int c; - int n; - if( argv[i][0]!='-' ){ - redraw = 1; - break; - } - c = argv[i][1]; - n = strlen(argv[i]); - if( c=='c' && n>4 && strncmp(argv[i],"-cursor",n)==0 ){ - /* do nothing */ - }else - /* The default case */ - { - redraw = 1; - } - } - rc = Tk_ConfigureWidget(interp, htmlPtr->tkwin, configSpecs, argc, (const char**)argv, - (char *) htmlPtr, flags); - if( rc!=TCL_OK || redraw==0 ){ TestPoint(0); return rc; } - memset(htmlPtr->fontValid, 0, sizeof(htmlPtr->fontValid)); - htmlPtr->apColor[COLOR_Normal] = htmlPtr->fgColor; - htmlPtr->apColor[COLOR_Visited] = htmlPtr->oldLinkColor; - htmlPtr->apColor[COLOR_Unvisited] = htmlPtr->newLinkColor; - htmlPtr->apColor[COLOR_Selection] = htmlPtr->selectionColor; - htmlPtr->apColor[COLOR_Background] = Tk_3DBorderColor(htmlPtr->border); - Tk_SetBackgroundFromBorder(htmlPtr->tkwin, htmlPtr->border); - if( htmlPtr->highlightWidth < 0 ){ htmlPtr->highlightWidth = 0; TestPoint(0);} - if (htmlPtr->padx < 0) { htmlPtr->padx = 0; TestPoint(0);} - if (htmlPtr->pady < 0) { htmlPtr->pady = 0; TestPoint(0);} - if (htmlPtr->width < 100) { htmlPtr->width = 100; TestPoint(0);} - if (htmlPtr->height < 100) { htmlPtr->height = 100; TestPoint(0);} - if (htmlPtr->borderWidth < 0) {htmlPtr->borderWidth = 0; TestPoint(0);} - htmlPtr->flags |= RESIZE_ELEMENTS | RELAYOUT | REDRAW_BORDER | RESIZE_CLIPWIN; - HtmlRecomputeGeometry(htmlPtr); - HtmlRedrawEverything(htmlPtr); - ClearGcCache(htmlPtr); - return rc; -} - -/* -** Delete a single HtmlElement -*/ -void HtmlDeleteElement(HtmlElement *p){ - switch( p->base.type ){ - case Html_Block: - if( p->block.z ){ - HtmlFree(p->block.z); - } - break; - default: - break; - } - HtmlFree(p); -} - -/* -** Erase all data from the HTML widget. Bring it back to an -** empty screen. -** -** This happens (for example) when the "clear" method is invoked -** on the widget, or just before the widget is deleted. -*/ -void HtmlClear(HtmlWidget *htmlPtr){ - int i; - HtmlElement *p, *pNext; - - HtmlDeleteControls(htmlPtr); - for(p=htmlPtr->pFirst; p; p=pNext){ - pNext = p->pNext; - HtmlDeleteElement(p); - } - htmlPtr->pFirst = 0; - htmlPtr->pLast = 0; - htmlPtr->nToken = 0; - if( htmlPtr->zText ){ - HtmlFree(htmlPtr->zText); - } - htmlPtr->zText = 0; - htmlPtr->nText = 0; - htmlPtr->nAlloc = 0; - htmlPtr->nComplete = 0; - htmlPtr->iPlaintext = 0; - for(i=N_PREDEFINED_COLOR; i<N_COLOR; i++){ - if( htmlPtr->apColor[i] != 0 ){ - Tk_FreeColor(htmlPtr->apColor[i]); - htmlPtr->apColor[i] = 0; - } - } - for(i=0; i<N_COLOR; i++){ - htmlPtr->iDark[i] = 0; - htmlPtr->iLight[i] = 0; - } - htmlPtr->colorUsed = 0; - while( htmlPtr->imageList ){ - HtmlImage *p = htmlPtr->imageList; - htmlPtr->imageList = p->pNext; - Tk_FreeImage(p->image); - HtmlFree(p); - TestPoint(0); - } - while( htmlPtr->styleStack ){ - HtmlStyleStack *p = htmlPtr->styleStack; - htmlPtr->styleStack = p->pNext; - HtmlFree(p); - } - ClearGcCache(htmlPtr); - ResetLayoutContext(htmlPtr); - if( htmlPtr->zBaseHref ){ - HtmlFree(htmlPtr->zBaseHref); - htmlPtr->zBaseHref = 0; - } - htmlPtr->lastSized = 0; - htmlPtr->nextPlaced = 0; - htmlPtr->firstBlock = 0; - htmlPtr->lastBlock = 0; - htmlPtr->nInput = 0; - htmlPtr->nForm = 0; - htmlPtr->varId = 0; - htmlPtr->paraAlignment = ALIGN_None; - htmlPtr->rowAlignment = ALIGN_None; - htmlPtr->anchorFlags = 0; - htmlPtr->inDt = 0; - htmlPtr->anchorStart = 0; - htmlPtr->formStart = 0; - htmlPtr->innerList = 0; - htmlPtr->maxX = 0; - htmlPtr->maxY = 0; - htmlPtr->xOffset = 0; - htmlPtr->yOffset = 0; - htmlPtr->pInsBlock = 0; - htmlPtr->ins.p = 0; - htmlPtr->selBegin.p = 0; - htmlPtr->selEnd.p = 0; - htmlPtr->pSelStartBlock = 0; - htmlPtr->pSelEndBlock = 0; -} - -/* -** This routine attempts to delete the widget structure. But it won't -** do it if the widget structure is locked. If the widget structure is -** locked, then when HtmlUnlock() is called and the lock count reaches -** zero, this routine will be called to finish the job. -*/ -static void DestroyHtmlWidget(HtmlWidget *htmlPtr){ - int i; - - if( htmlPtr->locked>0 ) return; - Tcl_DeleteCommand(htmlPtr->interp, htmlPtr->zCmdName); - Tcl_DeleteCommand(htmlPtr->interp, htmlPtr->zClipwin); - HtmlClear(htmlPtr); - Tk_FreeOptions(configSpecs, (char*) htmlPtr, htmlPtr->display, 0); - for(i=0; i<N_FONT; i++){ - if( htmlPtr->aFont[i] != 0 ){ - Tk_FreeFont(htmlPtr->aFont[i]); - htmlPtr->aFont[i] = 0; - } - } - for(i=0; i<Html_TypeCount; i++){ - if( htmlPtr->zHandler[i] ){ - HtmlFree(htmlPtr->zHandler[i]); - htmlPtr->zHandler[i] = 0; - } - } - if( htmlPtr->insTimer ){ - Tcl_DeleteTimerHandler(htmlPtr->insTimer); - htmlPtr->insTimer = 0; - } - HtmlFree(htmlPtr->zClipwin); - HtmlFree(htmlPtr); -} - -/* -** Remove a lock from the HTML widget. If the widget has been -** deleted, then delete the widget structure. Return 1 if the -** widget has been deleted. Return 0 if it still exists. -** -** Normal Tk code (that is to say, code in the Tk core) uses -** Tcl_Preserve() and Tcl_Release() to accomplish what this -** function does. But preserving and releasing are much more -** common in this code than in regular widgets, so this routine -** was invented to do the same thing easier and faster. -*/ -int HtmlUnlock(HtmlWidget *htmlPtr){ - htmlPtr->locked--; - if( htmlPtr->tkwin==0 && htmlPtr->locked<=0 ){ - Tcl_Interp *interp = htmlPtr->interp; - Tcl_Preserve(interp); - DestroyHtmlWidget(htmlPtr); - Tcl_Release(interp); - return 1; - } - return htmlPtr->tkwin==0; -} - -/* -** Lock the HTML widget. This prevents the widget structure from -** being deleted even if the widget itself is destroyed. There must -** be a call to HtmlUnlock() to release the structure. -*/ -void HtmlLock(HtmlWidget *htmlPtr){ - htmlPtr->locked++; -} - -/* -** This routine checks to see if an HTML widget has been -** destroyed. It is always called after calling HtmlLock(). -** -** If the widget has been destroyed, then the structure -** is unlocked and the function returns 1. If the widget -** has not been destroyed, then the structure is not unlocked -** and the routine returns 0. -** -** This routine is intended for use in code like the following: -** -** HtmlLock(htmlPtr); -** // Do something that might destroy the widget -** if( HtmlIsDead(htmlPtr) ) return; -** // Do something that might destroy the widget -** if( HtmlIsDead(htmlPtr) ) return; -** // Do something that might destroy the widget -** if( HtmlUnlock(htmlPtr) ) return; -*/ -int HtmlIsDead(HtmlWidget *htmlPtr){ - if( htmlPtr->tkwin==0 ){ - HtmlUnlock(htmlPtr); - return 1; - } - return 0; -} - -/* -** Flash the insertion cursor. -*/ -void HtmlFlashCursor(ClientData clientData){ - HtmlWidget *htmlPtr = (HtmlWidget*)clientData; - if( htmlPtr->pInsBlock==0 || htmlPtr->insOnTime<=0 - || htmlPtr->insOffTime<=0 ){ - htmlPtr->insTimer = 0; - TestPoint(0); - return; - } - HtmlRedrawBlock(htmlPtr, htmlPtr->pInsBlock); - if( (htmlPtr->flags & GOT_FOCUS)==0 ){ - htmlPtr->insStatus = 0; - htmlPtr->insTimer = 0; - TestPoint(0); - }else if( htmlPtr->insStatus ){ - htmlPtr->insTimer = Tcl_CreateTimerHandler(htmlPtr->insOffTime, - HtmlFlashCursor, clientData); - htmlPtr->insStatus = 0; - TestPoint(0); - }else{ - htmlPtr->insTimer = Tcl_CreateTimerHandler(htmlPtr->insOnTime, - HtmlFlashCursor, clientData); - htmlPtr->insStatus = 1; - TestPoint(0); - } -} - -/* -** Return a GC from the cache. As many as N_CACHE_GCs are kept valid -** at any one time. They are replaced using an LRU algorithm. -** -** A value of FONT_Any (-1) for the font means "don't care". -*/ -GC HtmlGetGC(HtmlWidget *htmlPtr, int color, int font){ - int i, j; - GcCache *p = htmlPtr->aGcCache; - XGCValues gcValues; - int mask; - Tk_Font tkfont; - - /* - ** Check for an existing GC. - */ - if( color < 0 || color >= N_COLOR ){ color = 0; TestPoint(0); } - if( font < FONT_Any || font >= N_FONT ){ font = FONT_Default; TestPoint(0); } - for(i=0; i<N_CACHE_GC; i++, p++){ - if( p->index==0 ){ TestPoint(0); continue; } - if( (font<0 || p->font==font) && p->color==color ){ - if( p->index>1 ){ - for(j=0; j<N_CACHE_GC; j++){ - if( htmlPtr->aGcCache[j].index - && htmlPtr->aGcCache[j].index < p->index ){ - htmlPtr->aGcCache[j].index++; - } - } - p->index = 1; - } - return htmlPtr->aGcCache[i].gc; - } - } - - /* - ** No GC matches. Find a place to allocate a new GC. - */ - p = htmlPtr->aGcCache; - for(i=0; i<N_CACHE_GC; i++, p++){ - if( p->index==0 || p->index==N_CACHE_GC ){ TestPoint(0); break; } - } - if( p->index ){ - Tk_FreeGC(htmlPtr->display, p->gc); - } - gcValues.foreground = htmlPtr->apColor[color]->pixel; - gcValues.graphics_exposures = True; - mask = GCForeground | GCGraphicsExposures; - if( font<0 ){ font = FONT_Default; TestPoint(0); } - tkfont = HtmlGetFont(htmlPtr, font); - if( tkfont ){ - gcValues.font = Tk_FontId(tkfont); - mask |= GCFont; - } - p->gc = Tk_GetGC(htmlPtr->tkwin, mask, &gcValues); - if( p->index==0 ){ p->index = N_CACHE_GC + 1; TestPoint(0); } - for(j=0; j<N_CACHE_GC; j++){ - if( htmlPtr->aGcCache[j].index && htmlPtr->aGcCache[j].index < p->index ){ - htmlPtr->aGcCache[j].index++; - } - } - p->index = 1; - p->font = font; - p->color = color; - return p->gc; -} - -/* -** Retrieve any valid GC. The font and color don't matter since the -** GC will only be used for copying. -*/ -GC HtmlGetAnyGC(HtmlWidget *htmlPtr){ - int i; - GcCache *p = htmlPtr->aGcCache; - - for(i=0; i<N_CACHE_GC; i++, p++){ - if( p->index ){ TestPoint(0); return p->gc; } - } - TestPoint(0); - return HtmlGetGC(htmlPtr, COLOR_Normal, FONT_Default); -} - -/* -** All window events (for both tkwin and clipwin) are -** sent to this routine. -*/ -static void HtmlEventProc(ClientData clientData, XEvent *eventPtr){ - HtmlWidget *htmlPtr = (HtmlWidget*) clientData; - int redraw_needed = 0; - XConfigureRequestEvent *p; - - switch( eventPtr->type ){ - case GraphicsExpose: - case Expose: - if( htmlPtr->tkwin==0 ){ - /* The widget is being deleted. Do nothing */ - TestPoint(0); - }else if( eventPtr->xexpose.window!=Tk_WindowId(htmlPtr->tkwin) ){ - /* Exposure in the clipping window */ - HtmlRedrawArea(htmlPtr, eventPtr->xexpose.x - 1, - eventPtr->xexpose.y - 1, - eventPtr->xexpose.x + eventPtr->xexpose.width + 1, - eventPtr->xexpose.y + eventPtr->xexpose.height + 1); - TestPoint(0); - }else{ - /* Exposure in the main window */ - htmlPtr->flags |= REDRAW_BORDER; - HtmlScheduleRedraw(htmlPtr); - TestPoint(0); - } - break; - case DestroyNotify: - if( (htmlPtr->flags & REDRAW_PENDING) ){ - Tcl_CancelIdleCall(HtmlRedrawCallback, (ClientData)htmlPtr); - htmlPtr->flags &= ~REDRAW_PENDING; - } - if( htmlPtr->tkwin != 0 ){ - if( eventPtr->xany.window!=Tk_WindowId(htmlPtr->tkwin) ){ - Tk_DestroyWindow(htmlPtr->tkwin); - htmlPtr->clipwin = 0; - break; - } - htmlPtr->tkwin = 0; - Tcl_DeleteCommand(htmlPtr->interp, htmlPtr->zCmdName); - Tcl_DeleteCommand(htmlPtr->interp, htmlPtr->zClipwin); - } - HtmlUnlock(htmlPtr); - break; - case ConfigureNotify: - if( htmlPtr->tkwin!=0 - && eventPtr->xconfigure.window==Tk_WindowId(htmlPtr->tkwin) - ){ - p = (XConfigureRequestEvent*)eventPtr; - if( p->width != htmlPtr->realWidth ){ - redraw_needed = 1; - htmlPtr->realWidth = p->width; - TestPoint(0); - }else{ - TestPoint(0); - } - if( p->height != htmlPtr->realHeight ){ - redraw_needed = 1; - htmlPtr->realHeight = p->height; - TestPoint(0); - }else{ - TestPoint(0); - } - if( redraw_needed ){ - htmlPtr->flags |= RELAYOUT | VSCROLL | HSCROLL | RESIZE_CLIPWIN; - HtmlRedrawEverything(htmlPtr); - TestPoint(0); - }else{ - TestPoint(0); - } - } - break; - case FocusIn: - if( htmlPtr->tkwin!=0 - && eventPtr->xfocus.window==Tk_WindowId(htmlPtr->tkwin) - && eventPtr->xfocus.detail != NotifyInferior - ){ - htmlPtr->flags |= GOT_FOCUS | REDRAW_FOCUS; - HtmlScheduleRedraw(htmlPtr); - HtmlUpdateInsert(htmlPtr); - TestPoint(0); - }else{ - TestPoint(0); - } - break; - case FocusOut: - if( htmlPtr->tkwin!=0 - && eventPtr->xfocus.window==Tk_WindowId(htmlPtr->tkwin) - && eventPtr->xfocus.detail != NotifyInferior - ){ - htmlPtr->flags &= ~GOT_FOCUS; - htmlPtr->flags |= REDRAW_FOCUS; - HtmlScheduleRedraw(htmlPtr); - TestPoint(0); - }else{ - TestPoint(0); - } - break; - } -} - - -/* -** The rendering and layout routines should call this routine in order to get -** a font structure. The iFont parameter specifies which of the N_FONT -** fonts should be obtained. The font is allocated if necessary. -** -** Because the -fontcommand callback can be invoked, this function can -** (in theory) cause the HTML widget to be changed arbitrarily or even -** deleted. Callers of this function much be prepared to be called -** recursively and/or to have the HTML widget deleted out from under -** them. This routine will return NULL if the HTML widget is deleted. -*/ -Tk_Font HtmlGetFont( - HtmlWidget *htmlPtr, /* The HTML widget to which the font applies */ - int iFont /* Which font to obtain */ -){ - Tk_Font toFree = 0; - - if( iFont<0 ){ iFont = 0; TestPoint(0); } - if( iFont>=N_FONT ){ iFont = N_FONT - 1; CANT_HAPPEN; } - - /* - ** If the font has previously been allocated, but the "fontValid" bitmap - ** shows it is no longer valid, then mark it for freeing later. We use - ** a policy of allocate-before-free because Tk's font cache operates - ** much more efficiently that way. - */ - if( !FontIsValid(htmlPtr, iFont) && htmlPtr->aFont[iFont]!=0 ){ - toFree = htmlPtr->aFont[iFont]; - htmlPtr->aFont[iFont] = 0; - TestPoint(0); - } - - /* - ** If we need to allocate a font, first construct the font name then - ** allocate it. - */ - if( htmlPtr->aFont[iFont]==0 ){ - char name[200]; /* Name of the font */ - - name[0] = 0; - - /* Run the -fontcommand if it is specified - */ - if( htmlPtr->zFontCommand && htmlPtr->zFontCommand[0] ){ - int iFam; /* The font family index. Value between 0 and 7 */ - Tcl_DString str; /* The command we'll execute to get the font name */ - char *zSep = ""; /* Separator between font attributes */ - int rc; /* Return code from the font command */ - char zBuf[100]; /* Temporary buffer */ - - Tcl_DStringInit(&str); - Tcl_DStringAppend(&str, htmlPtr->zFontCommand, -1); - sprintf(zBuf, " %d {", FontSize(iFont)+1); - Tcl_DStringAppend(&str,zBuf, -1); - iFam = iFont / N_FONT_SIZE ; - if( iFam & 1 ){ - Tcl_DStringAppend(&str,"bold",-1); - zSep = " "; - } - if( iFam & 2 ){ - Tcl_DStringAppend(&str,zSep,-1); - Tcl_DStringAppend(&str,"italic",-1); - zSep = " "; - } - if( iFam & 4 ){ - Tcl_DStringAppend(&str,zSep,-1); - Tcl_DStringAppend(&str,"fixed",-1); - } - Tcl_DStringAppend(&str,"}",-1); - HtmlLock(htmlPtr); - rc = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&str)); - Tcl_DStringFree(&str); - if( HtmlUnlock(htmlPtr) ){ - return NULL; - } - if( rc!=TCL_OK ){ - Tcl_AddErrorInfo(htmlPtr->interp, - "\n (-fontcommand callback of HTML widget)"); - Tcl_BackgroundError(htmlPtr->interp); - }else{ - sprintf(name,"%.100s", Tcl_GetStringResult(htmlPtr->interp)); - } - Tcl_ResetResult(htmlPtr->interp); - } - - /* - ** If the -fontcommand failed or returned an empty string, or if - ** there is no -fontcommand, then get the default font name. - */ - if( name[0]==0 ){ - char *familyStr = ""; - int iFamily; - int iSize; - int size; - - iFamily = iFont / N_FONT_SIZE; - iSize = iFont % N_FONT_SIZE + 1; - switch( iFamily ){ - case 0: familyStr = "helvetica -%d"; break; - case 1: familyStr = "helvetica -%d bold"; break; - case 2: familyStr = "helvetica -%d italic"; break; - case 3: familyStr = "helvetica -%d bold italic"; break; - case 4: familyStr = "courier -%d"; break; - case 5: familyStr = "courier -%d bold"; break; - case 6: familyStr = "courier -%d italic"; break; - case 7: familyStr = "courier -%d bold italic"; break; - default: familyStr = "helvetica -14"; CANT_HAPPEN; - } - switch( iSize ){ - case 1: size = 8; break; - case 2: size = 10; break; - case 3: size = 12; break; - case 4: size = 14; break; - case 5: size = 16; break; - case 6: size = 18; break; - case 7: size = 24; break; - default: size = 14; CANT_HAPPEN; - } - sprintf(name, familyStr, size); - } - - /* Get the named font - */ - htmlPtr->aFont[iFont] = Tk_GetFont(htmlPtr->interp, htmlPtr->tkwin, name); - if( htmlPtr->aFont[iFont]==0 ){ - Tcl_AddErrorInfo(htmlPtr->interp, - "\n (trying to create a font named \""); - Tcl_AddErrorInfo(htmlPtr->interp, name); - Tcl_AddErrorInfo(htmlPtr->interp, "\" in the HTML widget)"); - Tcl_BackgroundError(htmlPtr->interp); - htmlPtr->aFont[iFont] = - Tk_GetFont(htmlPtr->interp, htmlPtr->tkwin, "fixed"); - } - if( htmlPtr->aFont[iFont]==0 ){ - Tcl_AddErrorInfo(htmlPtr->interp, - "\n (trying to create font \"fixed\" in the HTML widget)"); - Tcl_BackgroundError(htmlPtr->interp); - htmlPtr->aFont[iFont] = - Tk_GetFont(htmlPtr->interp, htmlPtr->tkwin, "helvetica -12"); - } - FontSetValid(htmlPtr, iFont); - TestPoint(0); - } - - /* - ** Free the expired font, if any. - */ - if( toFree!=0 ){ - Tk_FreeFont(toFree); - } - return htmlPtr->aFont[iFont]; -} - -/* -** Compute the squared distance between two colors -*/ -static float colorDistance(XColor *pA, XColor *pB){ - float x, y, z; - - x = 0.30 * (pA->red - pB->red); - y = 0.61 * (pA->green - pB->green); - z = 0.11 * (pA->blue - pB->blue); - TestPoint(0); - return x*x + y*y + z*z; -} - -/* -** This routine returns an index between 0 and N_COLOR-1 which indicates -** which XColor structure in the apColor[] array of htmlPtr should be -** used to describe the color specified by the given name. -*/ -int HtmlGetColorByName(HtmlWidget *htmlPtr, char *zColor){ - XColor *pNew; - int iColor; - Tk_Uid name; - int i, n; - char zAltColor[16]; - - /* Netscape accepts color names that are just HEX values, without - ** the # up front. This isn't valid HTML, but we support it for - ** compatibility. - */ - n = strlen(zColor); - - /* trucate any spaces on the end */ - while (n>0 && zColor[n-1]==' ') { - zColor[n-1] = '\0'; - n--; - } - - if( n==6 || n==3 || n==9 || n==12 ){ - for(i=0; i<n; i++){ - if( !isxdigit(zColor[i]) ) break; - } - if( i==n ){ - sprintf(zAltColor,"#%s",zColor); - }else{ - strcpy(zAltColor, zColor); - } - name = Tk_GetUid(zAltColor); - }else{ - name = Tk_GetUid(zColor); - } - pNew = Tk_GetColor(htmlPtr->interp, htmlPtr->clipwin, name); - if( pNew==0 ){ - return 0; /* Color 0 is always the default */ - } - - iColor = GetColorByValue(htmlPtr, pNew); - Tk_FreeColor(pNew); - return iColor; -} - -/* -** Macros used in the computation of appropriate shadow colors. -*/ -#define MAX_COLOR 65535 -#define MAX(A,B) ((A)<(B)?(B):(A)) -#define MIN(A,B) ((A)<(B)?(A):(B)) - -/* -** Check to see if the given color is too dark to be easily distinguished -** from black. -*/ -static int isDarkColor(XColor *p){ - float x, y, z; - - x = 0.50 * p->red; - y = 1.00 * p->green; - z = 0.28 * p->blue; - return (x*x + y*y + z*z)<0.05*MAX_COLOR*MAX_COLOR; -} - -/* -** Given that the background color is iBgColor, figure out an -** appropriate color for the dark part of a 3D shadow. -*/ -int HtmlGetDarkShadowColor(HtmlWidget *htmlPtr, int iBgColor){ - if( htmlPtr->iDark[iBgColor]==0 ){ - XColor *pRef, val; - pRef = htmlPtr->apColor[iBgColor]; - if( isDarkColor(pRef) ){ - int t1, t2; - t1 = MIN(MAX_COLOR,pRef->red*1.2); - t2 = (pRef->red*3 + MAX_COLOR)/4; - val.red = MAX(t1,t2); - t1 = MIN(MAX_COLOR,pRef->green*1.2); - t2 = (pRef->green*3 + MAX_COLOR)/4; - val.green = MAX(t1,t2); - t1 = MIN(MAX_COLOR,pRef->blue*1.2); - t2 = (pRef->blue*3 + MAX_COLOR)/4; - val.blue = MAX(t1,t2); - }else{ - val.red = pRef->red*0.6; - val.green = pRef->green*0.6; - val.blue = pRef->blue*0.6; - } - htmlPtr->iDark[iBgColor] = GetColorByValue(htmlPtr, &val) + 1; - } - return htmlPtr->iDark[iBgColor] - 1; -} - -/* -** Check to see if the given color is too light to be easily distinguished -** from white. -*/ -static int isLightColor(XColor *p){ - return p->green>=0.85*MAX_COLOR; -} - -/* -** Given that the background color is iBgColor, figure out an -** appropriate color for the bright part of the 3D shadow. -*/ -int HtmlGetLightShadowColor(HtmlWidget *htmlPtr, int iBgColor){ - if( htmlPtr->iLight[iBgColor]==0 ){ - XColor *pRef, val; - pRef = htmlPtr->apColor[iBgColor]; - if( isLightColor(pRef) ){ - val.red = pRef->red*0.9; - val.green = pRef->green*0.9; - val.blue = pRef->blue*0.9; - }else{ - int t1, t2; - t1 = MIN(MAX_COLOR,pRef->green*1.4); - t2 = (pRef->green + MAX_COLOR)/2; - val.green = MAX(t1,t2); - t1 = MIN(MAX_COLOR,pRef->red*1.4); - t2 = (pRef->red + MAX_COLOR)/2; - val.red = MAX(t1,t2); - t1 = MIN(MAX_COLOR,pRef->blue*1.4); - t2 = (pRef->blue + MAX_COLOR)/2; - val.blue = MAX(t1,t2); - } - htmlPtr->iLight[iBgColor] = GetColorByValue(htmlPtr, &val) + 1; - } - return htmlPtr->iLight[iBgColor] - 1; -} - -/* -** Find a color integer for the color whose color components -** are given by pRef. -*/ -LOCAL int GetColorByValue(HtmlWidget *htmlPtr, XColor *pRef){ - int i; - float dist; - float closestDist; - int closest; - /* - int r, g, b; -# define COLOR_MASK 0xf800 - */ - - XColor* q; - q = Tk_GetColorByValue(htmlPtr->clipwin, pRef); - - /* Search for an exact match */ - /* - r = pRef->red &= COLOR_MASK; - g = pRef->green &= COLOR_MASK; - b = pRef->blue &= COLOR_MASK; - */ - for(i=0; i<N_COLOR; i++){ - XColor *p = htmlPtr->apColor[i]; - /* - if( p && (p->red & COLOR_MASK)==r && (p->green & COLOR_MASK)==g - && (p->blue & COLOR_MASK)==b ){ - */ - if (p && (q->red == p->red) - && (q->green == p->green) - && (q->blue == p->blue)) { - htmlPtr->colorUsed |= (1<<i); - Tk_FreeColor(q); - return i; - } - } - Tk_FreeColor(q); - - /* No exact matches. Look for a completely unused slot */ - for(i=N_PREDEFINED_COLOR; i<N_COLOR; i++){ - if( htmlPtr->apColor[i]==0 ){ - htmlPtr->apColor[i] = Tk_GetColorByValue(htmlPtr->clipwin, pRef); - htmlPtr->colorUsed |= (1<<i); - return i; - } - } - - /* No empty slots. Look for a slot that contains a color that - ** isn't currently in use. */ - for(i=N_PREDEFINED_COLOR; i<N_COLOR; i++){ - if( ((htmlPtr->colorUsed >> i) & 1) == 0 ){ - Tk_FreeColor(htmlPtr->apColor[i]); - htmlPtr->apColor[i] = Tk_GetColorByValue(htmlPtr->clipwin, pRef); - htmlPtr->colorUsed |= (1<<i); - return i; - } - } - - /* Ok, find the existing color that is closest to the color requested - ** and use it. */ - closest = 0; - closestDist = colorDistance(pRef, htmlPtr->apColor[0]); - for(i=1; i<N_COLOR; i++){ - dist = colorDistance(pRef, htmlPtr->apColor[i]); - if( dist < closestDist ){ - closestDist = dist; - closest = i; - } - } - return i; -} - -/* -** This routine searchs for a hyperlink beneath the coordinates x,y -** and returns a pointer to the HREF for that hyperlink. The text -** is held one of the markup.argv[] fields of the <a> markup. -*/ -char *HtmlGetHref(HtmlWidget *htmlPtr, int x, int y){ - HtmlBlock *pBlock; - HtmlElement *pElem; - - for(pBlock=htmlPtr->firstBlock; pBlock; pBlock=pBlock->pNext){ - if( pBlock->top > y || pBlock->bottom < y - || pBlock->left > x || pBlock->right < x - ){ - TestPoint(0); - continue; - } - pElem = pBlock->base.pNext; - if( (pElem->base.style.flags & STY_Anchor)==0 ){ TestPoint(0); continue; } - switch( pElem->base.type ){ - case Html_Text: - case Html_Space: - case Html_IMG: - while( pElem && pElem->base.type!=Html_A ){ - pElem = pElem->base.pPrev; - } - if( pElem==0 || pElem->base.type!=Html_A ){ break; } - return HtmlMarkupArg(pElem,"href", 0); - default: - break; - } - } - TestPoint(0); - return 0; -} - -/* -** Change the "yOffset" field from its current value to the value given. -** This has the effect of scrolling the widget vertically. -*/ -void HtmlVerticalScroll(HtmlWidget *htmlPtr, int yOffset){ - int inset; /* The 3D border plus the pady */ - int h; /* Height of the clipping window */ - int diff; /* Difference between old and new offset */ - GC gc; /* Graphics context used for copying */ - int w; /* Width of text area */ - - if( yOffset==htmlPtr->yOffset ){ TestPoint(0); return; } - inset = htmlPtr->pady + htmlPtr->inset; - h = htmlPtr->realHeight - 2*inset; - if( (htmlPtr->flags & REDRAW_TEXT)!=0 - || (htmlPtr->dirtyTop < h && htmlPtr->dirtyBottom > 0) - || htmlPtr->yOffset > yOffset + (h - 30) - || htmlPtr->yOffset < yOffset - (h - 30) - ){ - htmlPtr->yOffset = yOffset; - htmlPtr->flags |= VSCROLL | REDRAW_TEXT; - HtmlScheduleRedraw(htmlPtr); - TestPoint(0); - return; - } - diff = htmlPtr->yOffset - yOffset; - gc = HtmlGetAnyGC(htmlPtr); - w = htmlPtr->realWidth - 2*(htmlPtr->inset + htmlPtr->padx); - htmlPtr->flags |= VSCROLL; - htmlPtr->yOffset = yOffset; -#ifndef MAC_OSX_TK - if( diff < 0 ){ - XCopyArea(htmlPtr->display, - Tk_WindowId(htmlPtr->clipwin), /* source */ - Tk_WindowId(htmlPtr->clipwin), /* destination */ - gc, - 0, -diff, /* source X, Y */ - w, h + diff, /* Width and height */ - 0, 0); /* Destination X, Y */ - HtmlRedrawArea(htmlPtr, 0, h + diff, w, h); - TestPoint(0); - }else{ - XCopyArea(htmlPtr->display, - Tk_WindowId(htmlPtr->clipwin), /* source */ - Tk_WindowId(htmlPtr->clipwin), /* destination */ - gc, - 0, 0, /* source X, Y */ - w, h - diff, /* Width and height */ - 0, diff); /* Destination X, Y */ - HtmlRedrawArea(htmlPtr, 0, 0, w, diff); - TestPoint(0); - } -#else - HtmlRedrawArea(htmlPtr, 0, 0, w, h); -#endif - /* HtmlMapControls(htmlPtr);*/ -} - -/* -** Change the "xOffset" field from its current value to the value given. -** This has the effect of scrolling the widget horizontally. -*/ -void HtmlHorizontalScroll(HtmlWidget *htmlPtr, int xOffset){ - if( xOffset==htmlPtr->xOffset ){ TestPoint(0); return; } - htmlPtr->xOffset = xOffset; - HtmlMapControls(htmlPtr); - htmlPtr->flags |= HSCROLL | REDRAW_TEXT; - HtmlScheduleRedraw(htmlPtr); - TestPoint(0); -} - -/* -** The following array defines all possible widget command. The main -** widget command function just parses up the command line, then vectors -** control to one of the command service routines defined in the -** following array: -*/ -static struct HtmlSubcommand { - char *zCmd1; /* First-level subcommand. Required */ - char *zCmd2; /* Second-level subcommand. May be NULL */ - int minArgc; /* Minimum number of arguments */ - int maxArgc; /* Maximum number of arguments */ - char *zHelp; /* Help string if wrong number of arguments */ - int (*xFunc)(HtmlWidget*,Tcl_Interp*,int,const char**); /* Cmd service routine */ -} aSubcommand[] = { - { "cget", 0, 3, 3, "CONFIG-OPTION", HtmlCgetCmd }, - { "clear", 0, 2, 2, 0, HtmlClearCmd }, - { "configure", 0, 2, 0, "?ARGS...?", HtmlConfigCmd }, - { "href", 0, 4, 4, "X Y", HtmlHrefCmd }, - { "index", 0, 3, 3, "INDEX", HtmlIndexCmd }, - { "insert", 0, 3, 3, "INDEX", HtmlInsertCmd }, - { "names", 0, 2, 2, 0, HtmlNamesCmd }, - { "parse", 0, 3, 3, "HTML-TEXT", HtmlParseCmd }, - { "resolve", 0, 2, 0, "?URI ...?", HtmlResolveCmd }, - { "selection", "clear", 3, 3, 0, HtmlSelectionClearCmd}, - { 0, "set", 5, 5, "START END", HtmlSelectionSetCmd }, - { "text", "ascii", 5, 5, "START END", HtmlTextAsciiCmd}, - { 0, "delete", 5, 5, "START END", 0 }, - { 0, "html", 5, 5, "START END", 0 }, - { 0, "insert", 5, 5, "INDEX TEXT", 0 }, - { "token", "append", 5, 5, "TAG ARGUMENTS", 0 }, - { 0, "delete", 4, 5, "INDEX ?INDEX?", 0 }, - { 0, "find", 4, 6, "TAG ?before|after INDEX?", 0 }, - { 0, "get", 4, 5, "INDEX ?INDEX?", 0 }, - { 0, "handler", 4, 5, "TAG ?SCRIPT?", HtmlTokenHandlerCmd }, - { 0, "insert", 6, 6, "INDEX TAG ARGUMENTS", 0 }, - { 0, "list", 5, 5, "START END", HtmlTokenListCmd }, - { "xview", 0, 2, 5, "OPTIONS...", HtmlXviewCmd }, - { "yview", 0, 2, 5, "OPTIONS...", HtmlYviewCmd }, -#ifdef DEBUG - { "debug", "dump", 5, 5, "START END", HtmlDebugDumpCmd }, - { 0, "testpt", 4, 4, "FILENAME", HtmlDebugTestPtCmd }, -#endif -}; -#define nSubcommand (sizeof(aSubcommand)/sizeof(aSubcommand[0])) - -/* -** This routine implements the command used by individual HTML widgets. -*/ -static int HtmlWidgetCommand( - ClientData clientData, /* The HTML widget data structure */ - Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv /* Argument strings. */ -){ - HtmlWidget *htmlPtr = (HtmlWidget*) clientData; - size_t length; - int c; - int i; - struct HtmlSubcommand *pCmd; - - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " option ?arg arg ...?\"", 0); - TestPoint(0); - return TCL_ERROR; - } - c = argv[1][0]; - length = strlen(argv[1]); - for(i=0, pCmd=aSubcommand; i<nSubcommand; i++, pCmd++){ - if( pCmd->zCmd1==0 || c!=pCmd->zCmd1[0] - || strncmp(pCmd->zCmd1,argv[1],length)!=0 ){ - TestPoint(0); - continue; - } - if( pCmd->zCmd2 ){ - int length2; - int j; - if( argc<3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " ", pCmd->zCmd1, " SUBCOMMAND ?OPTIONS...?", 0); - TestPoint(0); - return TCL_ERROR; - } - length2 = strlen(argv[2]); - for(j=i; j<nSubcommand && (j==i || pCmd->zCmd1==0); j++, pCmd++){ - if( strncmp(pCmd->zCmd2,argv[2],length2)==0 ){ - TestPoint(0); - break; - } - } - if( j>=nSubcommand || (j!=i && aSubcommand[j].zCmd1!=0) ){ - Tcl_AppendResult(interp,"unknown subcommand \"", argv[2], - "\" -- should be one of:", 0); - for(j=i; j<nSubcommand && (j==i || aSubcommand[j].zCmd1==0); j++){ - Tcl_AppendResult(interp, " ", aSubcommand[j].zCmd2, 0); - TestPoint(0); - } - return TCL_ERROR; - } - } - if( argc<pCmd->minArgc || (argc>pCmd->maxArgc && pCmd->maxArgc>0) ){ - Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], - " ", pCmd->zCmd1, 0); - if( pCmd->zCmd2 ){ - Tcl_AppendResult(interp, " ", pCmd->zCmd2, 0); - TestPoint(0); - } - if( pCmd->zHelp ){ - Tcl_AppendResult(interp, " ", pCmd->zHelp, 0); - TestPoint(0); - } - Tcl_AppendResult(interp, "\"", 0); - TestPoint(0); - return TCL_ERROR; - } - if( pCmd->xFunc==0 ){ - Tcl_AppendResult(interp,"command not yet implemented", 0); - TestPoint(0); - return TCL_ERROR; - } - TestPoint(0); - return (*pCmd->xFunc)(htmlPtr, interp, argc, argv); - } - Tcl_AppendResult(interp,"unknown command \"", argv[1], "\" -- should be " - "one of:", 0); - for(i=0; i<nSubcommand; i++){ - if( aSubcommand[i].zCmd1==0 || aSubcommand[i].zCmd1[0]=='_' ){ - TestPoint(0); - continue; - } - Tcl_AppendResult(interp, " ", aSubcommand[i].zCmd1, 0); - TestPoint(0); - } - TestPoint(0); - return TCL_ERROR; -} - -/* -** The following routine implements the Tcl "html" command. This command -** is used to create new HTML widgets only. After the widget has been -** created, it is manipulated using the widget command defined above. -*/ -static int HtmlCommand( - ClientData clientData, /* Main window */ - Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv /* Argument strings. */ -){ - int n, c; - char *z; - - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " pathName ?options?\"", (char *) NULL); - return TCL_ERROR; - } - z = (char*)argv[1]; - n = strlen(z); - c = z[0]; - - /* If the first argument begins with ".", then it must be the - ** name of a new window the user wants to create. - */ - if( argv[1][0]=='.' ){ - HtmlWidget *htmlPtr; - Tk_Window new; - Tk_Window clipwin; - char *zClipwin; - Tk_Window tkwin = (Tk_Window)clientData; - static int varId = 1; /* Used to construct unique names */ - - new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL); - if (new == NULL) { - return TCL_ERROR; - } - zClipwin = HtmlAlloc( strlen(argv[1]) + 3 ); - if( zClipwin==0 ){ - Tk_DestroyWindow(new); - return TCL_ERROR; - } - sprintf(zClipwin,"%s.x",argv[1]); - clipwin = Tk_CreateWindowFromPath(interp, new, zClipwin, 0); - if( clipwin==0 ){ - Tk_DestroyWindow(new); - HtmlFree(zClipwin); - return TCL_ERROR; - } - - htmlPtr = HtmlAlloc(sizeof(HtmlWidget) + strlen(argv[1]) + 1); - memset(htmlPtr, 0, sizeof(HtmlWidget)); - htmlPtr->tkwin = new; - htmlPtr->clipwin = clipwin; - htmlPtr->zClipwin = zClipwin; - htmlPtr->display = Tk_Display(new); - htmlPtr->interp = interp; - htmlPtr->zCmdName = (char*)&htmlPtr[1]; - strcpy(htmlPtr->zCmdName, argv[1]); - htmlPtr->relief = TK_RELIEF_FLAT; - htmlPtr->dirtyLeft = LARGE_NUMBER; - htmlPtr->dirtyTop = LARGE_NUMBER; - htmlPtr->flags = RESIZE_CLIPWIN; - htmlPtr->varId = varId++; - Tcl_CreateCommand(interp, htmlPtr->zCmdName, - HtmlWidgetCommand, (ClientData)htmlPtr, HtmlCmdDeletedProc); - Tcl_CreateCommand(interp, htmlPtr->zClipwin, - HtmlWidgetCommand, (ClientData)htmlPtr, HtmlCmdDeletedProc); - - Tk_SetClass(new,"Html"); - Tk_SetClass(clipwin,"HtmlClip"); - Tk_CreateEventHandler(htmlPtr->tkwin, - ExposureMask|StructureNotifyMask|FocusChangeMask, - HtmlEventProc, (ClientData) htmlPtr); - Tk_CreateEventHandler(htmlPtr->clipwin, - ExposureMask|StructureNotifyMask, - HtmlEventProc, (ClientData) htmlPtr); - if (ConfigureHtmlWidget(interp, htmlPtr, argc-2, argv+2, 0, 1) != TCL_OK) { - goto error; - } - Tcl_SetResult(interp,Tk_PathName(htmlPtr->tkwin),NULL); - return TCL_OK; - - error: - Tk_DestroyWindow(htmlPtr->tkwin); - return TCL_ERROR; - } - - /* html reformat $from $to $text - ** - ** Convert the format of text. - */ - if( c=='r' && strncmp(z,"reformat",n)==0 ){ - if( argc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " reformat FROM TO TEXT", (char *) NULL); - return TCL_ERROR; - } - Tcl_AppendResult(interp, "not yet implemented", 0); - return TCL_ERROR; - }else - - - /* html urljoin $scheme $authority $path $query $fragment - ** - ** Merge together the parts of a URL into a single value URL. - */ - if( c=='u' && strncmp(z,"urljoin",n)==0 ){ - if( argc!=7 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " url join SCHEME AUTHORITY PATH QUERY FRAGMENT\"", 0); - return TCL_ERROR; - } - Tcl_AppendResult(interp, "not yet implemented", 0); - return TCL_ERROR; - }else - - - /* html urlsplit $url - ** - ** Split a URL into a list of its parts. - */ - if( c=='u' && strncmp(z,"urlsplit",n)==0 ){ - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " url split URL\"", 0); - return TCL_ERROR; - } - Tcl_AppendResult(interp, "not yet implemented", 0); - return TCL_ERROR; - }else - - /* No match. Report an error. - */ - { - Tcl_AppendResult(interp, "unknown command \"", z, "\": should be " - "a window name or one of: " - "reformat urljoin urlsplit", 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** The following mess is used to define DLL_EXPORT. DLL_EXPORT is -** blank except when we are building a Windows95/NT DLL from this -** library. Some special trickery is necessary to make this wall -** work together with makeheaders. -*/ -#if INTERFACE -#define DLL_EXPORT -#endif -#if defined(USE_TCL_STUBS) && defined(__WIN32__) -# undef DLL_EXPORT -# define DLL_EXPORT __declspec(dllexport) -#endif - -/* -** This routine is used to register the "html" command with the -** Tcl interpreter. This is the only routine in this file with -** external linkage. -*/ -DLL_EXPORT int Tkhtml1_Init(Tcl_Interp *interp) { - - if (Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0) == NULL) - return TCL_ERROR; - - if (Tk_InitStubs(interp, TK_PATCH_LEVEL, 0) == NULL) - return TCL_ERROR; - - Tcl_CreateCommand(interp,"html", HtmlCommand, Tk_MainWindow(interp), 0); - -#ifdef DEBUG - Tcl_LinkVar(interp, "HtmlTraceMask", (char*)&HtmlTraceMask, TCL_LINK_INT); -#endif - - if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION) != TCL_OK) - return TCL_ERROR; - - return TCL_OK; -} |