Esempio n. 1
0
/*
** Free an HtmlBlock structure.  Assume that it is already unlinked
** from the element list and the block list.
*/
static void FreeBlock(HtmlBlock *pBlock){
  if( pBlock ){
    if( pBlock->z ){
      HtmlFree(pBlock->z);
    }
    HtmlFree(pBlock);
  }
}
Esempio n. 2
0
/*
** Pop one margin off of the given margin stack.
*/
static void HtmlPopOneMargin(HtmlMargin **ppMargin){
  if( *ppMargin ){
    HtmlMargin *pOld = *ppMargin;
    *ppMargin = pOld->pNext;
    HtmlFree(pOld);
  }
}
Esempio n. 3
0
/*
** Replace the string in *pzDest with the string in zSrc
*/
static void ReplaceStr(char **pzDest, const char *zSrc){
  if( *pzDest!=0 ) HtmlFree(*pzDest);
  if( zSrc==0 ){
    *pzDest = 0;
  }else{
    *pzDest = StrNDup(zSrc, -1);
  }
}
Esempio n. 4
0
/*
 *---------------------------------------------------------------------------
 *
 * HtmlImageServerShutdown --
 *
 *     Shutdown and delete the image-server for html widget pTree. This
 *     function frees all resources allocated by HtmlImageServerInit().
 *
 * Results:
 *     None.
 *
 * Side effects:
 *     None.
 *
 *---------------------------------------------------------------------------
 */
void 
HtmlImageServerShutdown (HtmlTree *pTree)
{
    HtmlImageServer *p = pTree->pImageServer;
#ifndef NDEBUG
    Tcl_HashSearch search;
    Tcl_HashEntry *pEntry = Tcl_FirstHashEntry(&p->aImage, &search);
    assert(!pEntry);
#endif
    HtmlFree(p);
    pTree->pImageServer = 0;
}
Esempio n. 5
0
/*
** Delete an HtmlUri structure.
*/
static void FreeUri(HtmlUri *p){
  if( p==0 ) return;
  if( p->zScheme )    HtmlFree(p->zScheme);
  if( p->zAuthority ) HtmlFree(p->zAuthority);
  if( p->zPath )      HtmlFree(p->zPath);
  if( p->zQuery )     HtmlFree(p->zQuery);
  if( p->zFragment )  HtmlFree(p->zFragment);
  HtmlFree(p);
}
Esempio n. 6
0
/*
** For the markup <a href=XXX>, find out if the URL has been visited
** before or not.  Return COLOR_Visited or COLOR_Unvisited, as
** appropriate.
**
** This routine may invoke a callback procedure which could delete
** the HTML widget.  The calling function should call HtmlLock()
** if it needs the widget structure to be preserved.
*/
static int GetLinkColor(HtmlWidget *htmlPtr, char *zURL){
  char *zCmd;
  int result;
  int isVisited;

  if( htmlPtr->tkwin==0 ){
    TestPoint(0);
    return COLOR_Normal;
  }
  if( htmlPtr->zIsVisited==0 || htmlPtr->zIsVisited[0]==0 ){
    TestPoint(0);
    return COLOR_Unvisited;
  }
  zCmd = HtmlAlloc( strlen(htmlPtr->zIsVisited) + strlen(zURL) + 10 );
  if( zCmd==0 ){
    TestPoint(0);
    return COLOR_Unvisited;
  }
  sprintf(zCmd,"%s {%s}",htmlPtr->zIsVisited, zURL);
  HtmlLock(htmlPtr);
  result = Tcl_GlobalEval(htmlPtr->interp,zCmd);
  HtmlFree(zCmd);
  if( HtmlUnlock(htmlPtr) ){
    return COLOR_Unvisited;
  }
  if( result!=TCL_OK ){
    TestPoint(0);
    goto errorOut;
  }
  result = Tcl_GetBoolean(htmlPtr->interp,
                          Tcl_GetStringResult(htmlPtr->interp), &isVisited);
  if( result!=TCL_OK ){
    TestPoint(0);
    goto errorOut;
  }
  TestPoint(0);
  return isVisited ? COLOR_Visited : COLOR_Unvisited;

  errorOut:
  Tcl_AddErrorInfo(htmlPtr->interp,
    "\n    (\"-isvisitedcommand\" command executed by html widget)");
  Tcl_BackgroundError(htmlPtr->interp);
  TestPoint(0);
  return COLOR_Unvisited;
}
Esempio n. 7
0
/*
** Pop a rendering style off of the stack.
**
** The top-most style on the stack should have a tag equal to "tag".
** If not, then we have an HTML coding error.  Perhaps something
** like this:  "Some text <em>Enphasized</i> more text".  It is an
** interesting problem to figure out how to respond sanely to this
** kind of error.  Our solution it to keep popping the stack until
** we find the correct tag, or until the stack is empty.
*/
HtmlStyle HtmlPopStyleStack(HtmlWidget *htmlPtr, int tag){
  int type;
  HtmlStyleStack *p;
  static Html_u8 priority[Html_TypeCount+1];

  if( priority[Html_TABLE]==0 ){
    int i;
    for(i=0; i<=Html_TypeCount; i++) priority[i] = 1;
    priority[Html_TD] = 2;
    priority[Html_EndTD] = 2;
    priority[Html_TH] = 2;
    priority[Html_EndTH] = 2;
    priority[Html_TR] = 3;
    priority[Html_EndTR] = 3;
    priority[Html_TABLE] = 4;
    priority[Html_EndTABLE] = 4;
  }
  if( tag<=0 || tag>Html_TypeCount ){
    CANT_HAPPEN;
    return GetCurrentStyle(htmlPtr);
  }
  while( (p=htmlPtr->styleStack)!=0 ){
    type = p->type;
    if( type<=0 || type>Html_TypeCount ){
      CANT_HAPPEN;
      return GetCurrentStyle(htmlPtr);
    }
    if( type!=tag && priority[type]>priority[tag] ){
      return GetCurrentStyle(htmlPtr);
    }
    htmlPtr->styleStack = p->pNext;
    HtmlFree(p);
    if( type==tag ){ break; }
  }
  return GetCurrentStyle(htmlPtr);
}
Esempio n. 8
0
Tk_Image
HtmlImageImage(HtmlImage2 *pImage)
{
    assert(pImage && (pImage->isValid == 1 || pImage->isValid == 0));
    if (!pImage->isValid) {
        /* pImage->image is invalid. This happens if the underlying Tk
         * image, or the image that this is a scaled copy of, is changed
         * or deleted. It also happens the first time this function is
         * called after a call to HtmlImageScale().
         */ 
        Tk_PhotoHandle photo;
        Tk_PhotoImageBlock block;
        Tcl_Interp *interp = pImage->pImageServer->pTree->interp;
        HtmlImage2 *pUnscaled = pImage->pUnscaled;

        if (pUnscaled->pixmap) {
            Tcl_Obj *apObj[4];
            int rc;

/*printf("TODO: BAD. Have to recreate image to make scaled copy.\n");*/

            apObj[0] = pUnscaled->pImageName;
            apObj[1] = Tcl_NewStringObj("configure", -1);
            apObj[2] = Tcl_NewStringObj("-data", -1);
            apObj[3] = pUnscaled->pCompressed;

            Tcl_IncrRefCount(apObj[1]);
            Tcl_IncrRefCount(apObj[2]);
            Tcl_IncrRefCount(apObj[3]);
            pUnscaled->nIgnoreChange++;
            rc = Tcl_EvalObjv(interp, 4, apObj, TCL_EVAL_GLOBAL);
            pUnscaled->nIgnoreChange--;
            assert(rc==TCL_OK);
            Tcl_IncrRefCount(apObj[3]);
            Tcl_DecrRefCount(apObj[2]);
            Tcl_DecrRefCount(apObj[1]);
        }

        assert(pUnscaled);
        if (!pImage->pImageName) {
            /* If pImageName is still NULL, then create a new photo
             * image to write the scaled data to. Todo: Is it possible
             * to do this without invoking a script, creating the Tcl
             * command etc.?
             */
            Tk_Window win = pImage->pImageServer->pTree->tkwin;
            Tcl_Interp *interp = pImage->pImageServer->pTree->interp;
            const char *z;

            Tcl_Eval(interp, "image create photo");
            pImage->pImageName = Tcl_GetObjResult(interp);
            Tcl_IncrRefCount(pImage->pImageName);
            assert(0 == pImage->pDelete);
            assert(0 == pImage->image);

            z = Tcl_GetString(pImage->pImageName);
            pImage->image = Tk_GetImage(interp, win, z, imageChanged, pImage);
        }
        assert(pImage->image);

        CHECK_INTEGER_PLAUSIBILITY(pImage->width);
        CHECK_INTEGER_PLAUSIBILITY(pImage->height);
        CHECK_INTEGER_PLAUSIBILITY(pUnscaled->width);
        CHECK_INTEGER_PLAUSIBILITY(pUnscaled->height);

        /* Write the scaled data into image pImage->image */
        photo = Tk_FindPhoto(interp, Tcl_GetString(pUnscaled->pImageName));
        if (photo) {
            Tk_PhotoGetImage(photo, &block);
        }
        if (photo && block.pixelPtr) { 
            int x, y;                /* Iterator variables */
            int w, h;                /* Width and height of unscaled image */
            int sw, sh;              /* Width and height of scaled image */
            Tk_PhotoHandle s_photo;
            Tk_PhotoImageBlock s_block;

            sw = pImage->width;
            sh = pImage->height;
            w = pUnscaled->width;
            h = pUnscaled->height;
            s_photo = Tk_FindPhoto(interp, Tcl_GetString(pImage->pImageName));

            s_block.pixelPtr = (unsigned char *)HtmlAlloc("temp", sw * sh * 4);
            s_block.width = sw;
            s_block.height = sh;
            s_block.pitch = sw * 4;
            s_block.pixelSize = 4;
            s_block.offset[0] = 0;
            s_block.offset[1] = 1;
            s_block.offset[2] = 2;
            s_block.offset[3] = 3;

            for (x=0; x<sw; x++) {
                int orig_x = ((x * w) / sw);
                for (y=0; y<sh; y++) {
                    unsigned char *zOrig;
                    unsigned char *zScale;
                    int orig_y = ((y * h) / sh);

                    zOrig = &block.pixelPtr[
                        orig_x * block.pixelSize + orig_y * block.pitch];
                    zScale = &s_block.pixelPtr[
                        x * s_block.pixelSize + y * s_block.pitch];

                    zScale[0] = zOrig[block.offset[0]];
                    zScale[1] = zOrig[block.offset[1]];
                    zScale[2] = zOrig[block.offset[2]];
                    zScale[3] = zOrig[block.offset[3]];
                }
            }
            photoputblock(interp, s_photo, &s_block, 0, 0, sw, sh, 0);
            HtmlFree(s_block.pixelPtr);
        } else {
            return HtmlImageImage(pImage->pUnscaled);
        }

        pImage->isValid = 1;
        if (pUnscaled->pixmap) {
            Tcl_Obj *apObj[4];

            apObj[0] = Tcl_NewStringObj("image", -1);
            apObj[1] = Tcl_NewStringObj("create", -1);
            apObj[2] = Tcl_NewStringObj("photo", -1);
            apObj[3] = pUnscaled->pImageName;

            Tcl_IncrRefCount(apObj[0]);
            Tcl_IncrRefCount(apObj[1]);
            Tcl_IncrRefCount(apObj[2]);
            pUnscaled->nIgnoreChange++;
            Tcl_EvalObjv(interp, 4, apObj, TCL_EVAL_GLOBAL);
            pUnscaled->nIgnoreChange--;
            Tcl_DecrRefCount(apObj[2]);
            Tcl_DecrRefCount(apObj[1]);
            Tcl_IncrRefCount(apObj[0]);
        }
    }

    return pImage->image;
}
Esempio n. 9
0
static void
freeCaseInsensitiveEntry(Tcl_HashEntry *hPtr)
{
    HtmlFree(hPtr);
}
Esempio n. 10
0
/*
** The input azSeries[] is a sequence of URIs.  This command must
** resolve them all and put the result in the interp->result field
** of the interpreter associated with the HTML widget.  Return 
** TCL_OK on success and TCL_ERROR if there is a failure.
**
** This function can cause the HTML widget to be deleted or changed
** arbitrarily. 
*/
int HtmlCallResolver(
  HtmlWidget *htmlPtr,      /* The widget that is doing the resolving. */
  char **azSeries           /* A list of URIs.  NULL terminated */
){
  int rc = TCL_OK;          /* Return value of this function. */
  char *z;

  HtmlVerifyLock(htmlPtr);
  if( htmlPtr->zResolverCommand && htmlPtr->zResolverCommand[0] ){
    /*
    ** Append the current base URI then the azSeries arguments to the
    ** TCL command specified by the -resolvercommand optoin, then execute
    ** the result.
    **
    ** The -resolvercommand could do nasty things, such as delete
    ** the HTML widget out from under us.  Be prepared for the worst.
    */
    Tcl_DString cmd;
    Tcl_DStringInit(&cmd);
    Tcl_DStringAppend(&cmd, htmlPtr->zResolverCommand, -1);
    if( htmlPtr->zBaseHref && htmlPtr->zBaseHref[0] ){
      z = Trim(htmlPtr->zBaseHref);
    }else if( htmlPtr->zBase && htmlPtr->zBase[0] ){
      z = Trim(htmlPtr->zBase);
    }
    if( z ){
      Tcl_DStringAppendElement(&cmd, z);
      HtmlFree(z);
    }
    while( azSeries[0] ){
      z = Trim(azSeries[0]);
      if( z ){
        Tcl_DStringAppendElement(&cmd, z);
        HtmlFree(z);
      }
      azSeries++;
    }
    HtmlLock(htmlPtr);
    rc = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
    Tcl_DStringFree(&cmd);
    if( HtmlUnlock(htmlPtr) ) return TCL_ERROR;
    if( rc!=TCL_OK ){
      Tcl_AddErrorInfo(htmlPtr->interp,
         "\n    (-resolvercommand executed by HTML widget)");
    }
  }else{
    /*
    ** No -resolvercommand has been specified.  Do the default
    ** resolver algorithm specified in section 5.2 of RFC 2396.
    */
    HtmlUri *base, *term;
    if( htmlPtr->zBaseHref && htmlPtr->zBaseHref[0] ){
      base = ParseUri(htmlPtr->zBaseHref);
    }else{
      base = ParseUri(htmlPtr->zBase);
    }
    while( azSeries[0] ){
      term = ParseUri(azSeries[0]);
      azSeries++;
      if( term->zScheme==0 && term->zAuthority==0 && term->zPath==0
          && term->zQuery==0 && term->zFragment ){
        ReplaceStr(&base->zFragment, term->zFragment);
      }else if( term->zScheme ){
        HtmlUri temp;
        temp = *term;
        *term = *base;
        *base = temp;
      }else if( term->zAuthority ){
        ReplaceStr(&base->zAuthority, term->zAuthority);
        ReplaceStr(&base->zPath, term->zPath);
        ReplaceStr(&base->zQuery, term->zQuery);
        ReplaceStr(&base->zFragment, term->zFragment);
      }else if( term->zPath && (term->zPath[0]=='/' || base->zPath==0) ){
        ReplaceStr(&base->zPath, term->zPath);
        ReplaceStr(&base->zQuery, term->zQuery);
        ReplaceStr(&base->zFragment, term->zFragment);
      }else if( term->zPath && base->zPath ){
        char *zBuf;
        int i, j;
        zBuf = HtmlAlloc( strlen(base->zPath) + strlen(term->zPath) + 2 );
        if( zBuf ){
          sprintf(zBuf,"%s", base->zPath);
          for(i=strlen(zBuf)-1; i>=0 && zBuf[i]!='/'; i--){ zBuf[i] = 0; }
          strcat(zBuf, term->zPath);
          for(i=0; zBuf[i]; i++){
            if( zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]=='/' ){
              strcpy(&zBuf[i+1], &zBuf[i+3]);
              i--;
              continue;
            }
            if( zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]==0 ){
              zBuf[i+1] = 0;
              continue;
            }
            if( i>0 && zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]=='.'
                   && (zBuf[i+3]=='/' || zBuf[i+3]==0) ){
              for(j=i-1; j>=0 && zBuf[j]!='/'; j--){}
              if( zBuf[i+3] ){
                strcpy(&zBuf[j+1], &zBuf[i+4]);
              }else{
                zBuf[j+1] = 0;
              }
              i = j-1;
              if( i<-1 ) i = -1;
              continue;
            }
          }
          HtmlFree(base->zPath);
          base->zPath = zBuf;
        }
        ReplaceStr(&base->zQuery, term->zQuery);
        ReplaceStr(&base->zFragment, term->zFragment);
     }
      FreeUri(term);
    }
    Tcl_SetResult(htmlPtr->interp, BuildUri(base), TCL_DYNAMIC);
    FreeUri(base);
  }
  return rc;
}
Esempio n. 11
0
/*
** Recompute the following fields of the given block structure:
**
**    base.count         The number of elements described by this
**                       block structure.
**
**    n                  The number of characters of text output
**                       associated with this block.  If the block
**                       renders something other than text (ex: <IMG>)
**                       then set n to 0.
**
**    z                  Pointer to malloced memory containing the
**                       text associated with this block.  NULL if
**                       n is 0.
**
** Return a pointer to the first HtmlElement not covered by the
** block.
*/
static HtmlElement *FillOutBlock(HtmlWidget *htmlPtr, HtmlBlock *p){
  HtmlElement *pElem;
  int go;
  int n;
  int x, y;
  int i;
  HtmlStyle style;
  int firstSelected;      /* First selected character in this block */
  int lastSelected;       /* Last selected character in this block */
  char zBuf[400];

  /*
  ** Reset n and z
  */
  if( p->n ){
    p->n = 0;
  }
  if( p->z ){
    HtmlFree(p->z);
  }
  firstSelected = 1000000;
  lastSelected = -1;

  /*
  ** Skip over HtmlElements that aren't directly displayed.
  */
  pElem = p->base.pNext;
  p->base.count = 0;
  while( pElem && (pElem->base.flags & HTML_Visible)==0 ){
    HtmlElement *pNext = pElem->pNext;
    if( pElem->base.type==Html_Block ){
      UnlinkAndFreeBlock(htmlPtr, &pElem->block);
      TestPoint(0);
    }else{
      p->base.count++;
      TestPoint(0);
    }
    pElem = pNext;
  }
  if( pElem==0 ){ TestPoint(0); return 0; }

  /*
  ** Handle "special" elements.
  */
  if( pElem->base.type!=Html_Text ){
    switch( pElem->base.type ){
      case Html_HR:
        p->top = pElem->hr.y - pElem->hr.h;
        p->bottom = pElem->hr.y;
        p->left = pElem->hr.x;
        p->right = pElem->hr.x + pElem->hr.w;
        TestPoint(0);
        break;
      case Html_LI:
        p->top = pElem->li.y - pElem->li.ascent;
        p->bottom = pElem->li.y + pElem->li.descent;
        p->left = pElem->li.x - 10;
        p->right = pElem->li.x + 10;
        TestPoint(0);
        break;
      case Html_TD:
      case Html_TH:
        p->top = pElem->cell.y;
        p->bottom = pElem->cell.y + pElem->cell.h;
        p->left = pElem->cell.x;
        p->right = pElem->cell.x + pElem->cell.w;
        TestPoint(0);
        break;
      case Html_TABLE:
        p->top = pElem->table.y;
        p->bottom = pElem->table.y + pElem->table.h;
        p->left = pElem->table.x;
        p->right = pElem->table.x + pElem->table.w;
        TestPoint(0);
        break;
      case Html_IMG:
        p->top = pElem->image.y - pElem->image.ascent;
        p->bottom = pElem->image.y + pElem->image.descent;
        p->left = pElem->image.x;
        p->right = pElem->image.x + pElem->image.w;
        TestPoint(0);
        break;
    }
    p->base.count++;
    TestPoint(0);
    return pElem->pNext;
  }

  /*
  ** If we get this far, we must be dealing with text.
  */
  n = 0;
  x = pElem->text.x;
  y = pElem->text.y;
  p->top = y - pElem->text.ascent;
  p->bottom = y + pElem->text.descent;
  p->left = x;
  style = pElem->base.style;
  go = 1;
  while( pElem ){
    HtmlElement *pNext = pElem->pNext;
    switch( pElem->base.type ){
      case Html_Text:
        if( pElem->base.style.flags & STY_Invisible ){
          TestPoint(0);
          break;
        }
        if( pElem->text.spaceWidth <=0 ){
          CANT_HAPPEN;
          break;
        }
        if( y != pElem->text.y 
        ||  style.font != pElem->base.style.font
        ||  style.color != pElem->base.style.color
        ||  (style.flags & STY_FontMask) 
              != (pElem->base.style.flags & STY_FontMask)
        ){
          go = 0;
          TestPoint(0);
        }else{
          int sw = pElem->text.spaceWidth;
          int nSpace = (pElem->text.x - x) / sw;
          if( nSpace * sw + x != pElem->text.x ){
            go = 0;
            TestPoint(0);
          }else if( n + nSpace + pElem->base.count >= sizeof(zBuf) ){
            go = 0;
            TestPoint(0);
          }else{
            for(i=0; i<nSpace; i++){
              zBuf[n++] = ' ';
              TestPoint(0);
            }
            strcpy(&zBuf[n], pElem->text.zText);
            n += pElem->base.count;
            x = pElem->text.x + pElem->text.w;
          }
        }
        break;

      case Html_Space:
        if( pElem->base.style.font != style.font ){
          pElem = pElem->pNext;
          go = 0;
        }else if( (style.flags & STY_Preformatted)!=0 
                  && (pElem->base.flags & HTML_NewLine)!=0 ){
          pElem = pElem->pNext;
          go = 0;
        }
        break;

      case Html_Block:
        UnlinkAndFreeBlock(htmlPtr,&pElem->block);
        break;

      case Html_A:
      case Html_EndA:
        go = 0;
        break;

      default:
        if( pElem->base.flags & HTML_Visible ) go = 0;
        TestPoint(0);
        break;
    }
    if( go==0 ) break;
    p->base.count++;
    pElem = pNext;
  }
  p->right = x;

  while( n>0 && zBuf[n-1]==' ' ){ TestPoint(0); n--; }
  p->z = HtmlAlloc( n );
  strncpy(p->z, zBuf, n);
  p->n = n;
  return pElem;
}
Esempio n. 12
0
static void
freeValuesEntry(Tcl_HashEntry *hPtr)
{
    HtmlFree(hPtr);
}
Esempio n. 13
0
/*
** This routine takes a text representation of a token, converts
** it into an HtmlElement structure and inserts it immediately 
** prior to pToken.  If pToken==0, then the newly created HtmlElement
** is appended.
**
** This routine does nothing to resize, restyle, relayout or redisplay
** the HTML.  That is the calling routines responsibility.
**
** Return 0 if successful.  Return non-zero if zType is not a known
** markup name.
*/
int HtmlInsertToken(
  HtmlWidget *htmlPtr,     /* The widget into which the token is inserted */
  HtmlElement *pToken,     /* Insert before this.  Append if pToken==0 */
  char *zType,             /* Type of markup.  Ex: "/a" or "table" */
  char *zArgs              /* List of arguments */
){
  HtmlTokenMap *pMap;     /* For searching the markup name hash table */
  int h;                   /* The hash on zType */
  HtmlElement *pElem;      /* The new element */
  int nByte;               /* How many bytes to allocate */
  int i;                   /* Loop counter */

  if( !isInit ){
    HtmlHashInit();
    isInit = 1;
    TestPoint(0);
  }else{
    TestPoint(0);
  }
  h = HtmlHash(zType);
  for(pMap = apMap[h]; pMap; pMap=pMap->pCollide){
    if( stricmp(pMap->zName,zType)==0 ){ TestPoint(0); break; }
    TestPoint(0);
  }
  if( pMap==0 ){ TestPoint(0); return 1; }

  if( zArgs==0 || *zArgs==0 ){
    /* Special case of no arguments.  This is a lot easier... */
    nByte = pMap->extra ? pMap->extra : sizeof(HtmlBaseElement);
    nByte += strlen(zType);
    pElem = HtmlAlloc( nByte );
    if( pElem==0 ){ TestPoint(0); return 1; }
    memset(pElem,0,nByte);
    pElem->base.type = pMap->type;
    TestPoint(0);
  }else{
    /* The general case.  There are arguments that need to be parsed
    ** up.  This is slower, but we gotta do it.
    */
    int argc;
    char **argv;
    char *zBuf;

    if( Tcl_SplitList(htmlPtr->interp, zArgs, &argc, &argv)!=TCL_OK ){
      TestPoint(0);
      return 1;
    }
    if( pMap->extra ){
      nByte = pMap->extra;
      TestPoint(0);
    }else{
      nByte = sizeof(HtmlMarkupElement);
      TestPoint(0);
    }
    nByte += sizeof(char*)*(argc+1) + strlen(zArgs) + argc + 2;
    pElem = HtmlAlloc( nByte );
    if( pElem==0 ){
      HtmlFree(argv);
      TestPoint(0);
      return 1;
    }
    memset(pElem,0,nByte);
    pElem->base.type = pMap->type;
    pElem->base.count = argc;
    if( pMap->extra ){
      pElem->markup.argv = (char**)&((char*)pElem)[pMap->extra];
      TestPoint(0);
    }else{
      pElem->markup.argv = (char**)&((HtmlMarkupElement*)pElem)[1];
      TestPoint(0);
    }
    zBuf = (char*)&pElem->markup.argv[argc];
    for(i=1; i<argc; i++){
      pElem->markup.argv[i-1] = zBuf;
      zBuf += strlen(argv[i]) + 1;
      strcpy(pElem->markup.argv[i-1],argv[i]);
      TestPoint(0);
    }
    pElem->markup.argv[argc-1] = 0;
    HtmlFree(argv);
    TestPoint(0);
  }
  if( pToken ){
    pElem->base.pNext = pToken;
    pElem->base.pPrev = pToken->base.pPrev;
    if( pToken->base.pPrev ){
      pToken->base.pPrev->pNext = pElem;
      TestPoint(0);
    }else{
      htmlPtr->pFirst = pElem;
      TestPoint(0);
    }
    pToken->base.pPrev = pElem;
    htmlPtr->nToken++;
  }else{
    AppendElement(htmlPtr,pElem);
    TestPoint(0);
  }
  return 0;
}
Esempio n. 14
0
/*
** 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;
  const 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 = 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;
}
Esempio n. 15
0
/* Process as much of the input HTML as possible.  Construct new
** HtmlElement structures and appended them to the list.  Return
** the number of characters actually processed.
**
** This routine may invoke a callback procedure which could delete
** the HTML widget. 
**
** This routine is not reentrant for the same HTML widget.  To
** prevent reentrancy (during a callback), the p->iCol field is
** set to a negative number.  This is a flag to future invocations
** not to reentry this routine.  The p->iCol field is restored
** before exiting, of course.
*/
static int Tokenize(
  HtmlWidget *p        /* The HTML widget doing the parsing */
){
  char *z;             /* The input HTML text */
  int c;               /* The next character of input */
  int n;               /* Number of characters processed so far */
  int iCol;            /* Column of input */
  int i, j;            /* Loop counters */
  int h;               /* Result from HtmlHash() */
  int nByte;           /* Space allocated for a single HtmlElement */
  HtmlElement *pElem;  /* A new HTML element */
  int selfClose;       /* True for content free elements.  Ex:  <br/> */
  int argc;            /* The number of arguments on a markup */
  HtmlTokenMap *pMap;  /* For searching the markup name hash table */
  char *zBuf;          /* For handing out buffer space */
# define mxARG 200     /* Maximum number of parameters in a single markup */
  char *argv[mxARG];   /* Pointers to each markup argument. */
  int arglen[mxARG];   /* Length of each markup argument */

  iCol = p->iCol;
  n = p->nComplete;
  z = p->zText;
  if( iCol<0 ){ TestPoint(0); return n; }   /* Prevents recursion */
  p->iCol = -1;
  while( (c=z[n])!=0 ){
    if( p->pScript ){
      /* We are in the middle of <SCRIPT>...</SCRIPT>.  Just look for
      ** the </SCRIPT> markup.  (later:)  Treat <STYLE>...</STYLE> the
      ** same way. */
      HtmlScript *pScript = p->pScript;
      char *zEnd;
      int nEnd;
      if( pScript->markup.base.type==Html_SCRIPT ){
        zEnd = "</script>";
        nEnd = 9;
      }else{
        zEnd = "</style>";
        nEnd = 8;
      }
      if( pScript->zScript==0 ){
        pScript->zScript = &z[n];
        pScript->nScript = 0;
      }
      for(i=n+pScript->nScript; z[i]; i++){
        if( z[i]=='<' && z[i+1]=='/' && strnicmp(&z[i],zEnd,nEnd)==0 ){
          pScript->nScript = i - n;
          p->pScript = 0;
          n = i+nEnd;
          break;
        }
      }
      if( p->pScript ){
        pScript->nScript = i - n;
      }
      continue;
    }else if( isspace(c) ){
      /* White space */
      for(i=0; (c=z[n+i])!=0 && isspace(c) && c!='\n' && c!='\r'; i++){}
      if( c=='\r' && z[n+i+1]=='\n' ){ i++; }
      pElem = HtmlAlloc( sizeof(HtmlSpaceElement) );
      if( pElem==0 ){ goto incomplete; }
      pElem->base.type = Html_Space;
      if( c=='\n' || c=='\r' ){
        pElem->base.flags = HTML_NewLine;
        pElem->base.count = 1;
        i++;
        iCol = 0;
        TestPoint(0);
      }else{
        int iColStart = iCol;
        pElem->base.flags = 0;
        for(j=0; j<i; j++){
          iCol = NextColumn(iCol, z[n+j]);
          TestPoint(0);
        }
        pElem->base.count = iCol - iColStart;
      }
      AppendElement(p,pElem);
      n += i;
    }else if( c!='<' || p->iPlaintext!=0 || 
      (!isalpha(z[n+1]) && z[n+1]!='/' && z[n+1]!='!' && z[n+1]!='?') ){
      /* Ordinary text */
      for(i=1; (c=z[n+i])!=0 && !isspace(c) && c!='<'; i++){}
      if( c==0 ){ TestPoint(0); goto incomplete; }
      if( p->iPlaintext!=0 && z[n]=='<' ){
        switch( p->iPlaintext ){
          case Html_LISTING:
            if( i>=10 && strnicmp(&z[n],"</listing>",10)==0 ){
              p->iPlaintext = 0;
              goto doMarkup;
            }
            break;
          case Html_XMP:
            if( i>=6 && strnicmp(&z[n],"</xmp>",6)==0 ){
              p->iPlaintext = 0;
              goto doMarkup;
            }
            break;
          case Html_TEXTAREA:
            if( i>=11 && strnicmp(&z[n],"</textarea>",11)==0 ){
              p->iPlaintext = 0;
              goto doMarkup;
            }
            break;
          default:
            break;
        }
      }
      nByte = sizeof(HtmlTextElement) + i;
      pElem = HtmlAlloc( nByte );
      if( pElem==0 ){ goto incomplete; }
      memset(pElem,0,nByte);
      pElem->base.type = Html_Text;
      sprintf(pElem->text.zText,"%.*s",i,&z[n]);
      AppendElement(p,pElem);
      if( p->iPlaintext==0 || p->iPlaintext==Html_TEXTAREA ){
        HtmlTranslateEscapes(pElem->text.zText);
      }
      pElem->base.count = strlen(pElem->text.zText);
      n += i;
      iCol += i;
    }else if( strncmp(&z[n],"<!--",4)==0 ){
      /* An HTML comment.  Just skip it. */
      for(i=4; z[n+i]; i++){
        if( z[n+i]=='-' && strncmp(&z[n+i],"-->",3)==0 ){ break; }
      }
      if( z[n+i]==0 ){ TestPoint(0); goto incomplete; }
      for(j=0; j<i+3; j++){
        iCol = NextColumn(iCol, z[n+j]);
      }
      n += i + 3;
    }else{
      /* Markup.
      **
      ** First get the name of the markup
      */
doMarkup:
      argc = 1;
      argv[0] = &z[n+1];
      for(i=1; (c=z[n+i])!=0 && !isspace(c) && c!='>' && (i<2 || c!='/'); i++){}
      arglen[0] = i - 1;
      if( c==0 ){ goto incomplete; }

      /*
      ** Now parse up the arguments
      */
      while( isspace(z[n+i]) ){ i++; }
      while( (c=z[n+i])!=0 && c!='>' && (c!='/' || z[n+i+1]!='>') ){
        if( argc>mxARG-3 ){
          argc = mxARG-3;
        }
        argv[argc] = &z[n+i];
        j = 0;
        while( (c=z[n+i+j])!=0 && !isspace(c) && c!='>' 
               && c!='=' && (c!='/' || z[n+i+j+1]!='>') ){
          j++;
        }
        arglen[argc] = j;
        if( c==0 ){  goto incomplete; }
        i += j;
        while( isspace(c) ){
          i++;
          c = z[n+i];
        }
        if( c==0 ){ goto incomplete; }
        argc++;
        if( c!='=' ){
          argv[argc] = "";
          arglen[argc] = 0;
          argc++;
          continue;
        }
        i++;
        c = z[n+i];
        while( isspace(c) ){
          i++;
          c = z[n+i];
        }
        if( c==0 ){ goto incomplete; }
        if( c=='\'' || c=='"' ){
          int cQuote = c;
          i++;
          argv[argc] = &z[n+i];
          for(j=0; (c=z[n+i+j])!=0 && c!=cQuote; j++){}
          if( c==0 ){ goto incomplete; }
          arglen[argc] = j;
          i += j+1;
          TestPoint(0);
        }else{
          argv[argc] = &z[n+i];
          for(j=0; (c=z[n+i+j])!=0 && !isspace(c) && c!='>'; j++){}
          if( c==0 ){ goto incomplete; }
          arglen[argc] = j;
          i += j;
        }
        argc++;
        while( isspace(z[n+i]) ){ i++; }
      }
      if( c=='/' ){
        i++;
        c = z[n+i];
        selfClose = 1;
      }else{
        selfClose = 0;
      }
      if( c==0 ){ goto incomplete; }
      for(j=0; j<i+1; j++){
        iCol = NextColumn(iCol, z[n+j]);
      }
      n += i + 1;

      /* Lookup the markup name in the hash table 
      */
      if( !isInit ){
        HtmlHashInit();
        isInit = 1;
      }
      c = argv[0][arglen[0]];
      argv[0][arglen[0]] = 0;
      h = HtmlHash(argv[0]);
      for(pMap = apMap[h]; pMap; pMap=pMap->pCollide){
        if( stricmp(pMap->zName,argv[0])==0 ){ break; }
        TestPoint(0);
      }
      argv[0][arglen[0]] = c;
      if( pMap==0 ){ continue; }  /* Ignore unknown markup */

makeMarkupEntry:
      /* Construct a HtmlMarkup entry for this markup.
      */ 
      if( pMap->extra ){
        nByte = pMap->extra;
      }else if( argc==1 ){
        nByte = sizeof(HtmlBaseElement);
      }else{
        nByte = sizeof(HtmlMarkupElement);
      }
      if( argc>1 ){
        nByte += sizeof(char*) * argc;
        for(j=1; j<argc; j++){
          nByte += arglen[j] + 1;
        }
      }
      pElem = HtmlAlloc( nByte );
      if( pElem==0 ){ goto incomplete; }
      memset(pElem,0,nByte);
      pElem->base.type = pMap->type;
      pElem->base.count = argc - 1;
      if( argc>1 ){
        if( pMap->extra ){
          pElem->markup.argv = (char**)&((char*)pElem)[pMap->extra];
        }else{
          pElem->markup.argv = (char**)&((HtmlMarkupElement*)pElem)[1];
        }
        zBuf = (char*)&pElem->markup.argv[argc];
        for(j=1; j<argc; j++){
          pElem->markup.argv[j-1] = zBuf;
          zBuf += arglen[j] + 1;
          sprintf(pElem->markup.argv[j-1],"%.*s",arglen[j],argv[j]);
          HtmlTranslateEscapes(pElem->markup.argv[j-1]);
          if( (j&1)==1 ){
            ToLower(pElem->markup.argv[j-1]);
          }
        }
        pElem->markup.argv[argc-1] = 0;
      }

      /* The new markup has now be constructed in pElem.  But before
      ** appending to the list, check to see if there is a special
      ** handler for this markup type.
      */
      if( p->zHandler[pMap->type] ){
        Tcl_DString str;
        Tcl_DStringInit(&str);
        Tcl_DStringAppend(&str, p->zHandler[pMap->type], -1);
        Tcl_DStringAppendElement(&str, pMap->zName);
        Tcl_DStringStartSublist(&str);
        for(j=0; j<argc-1; j++){
          Tcl_DStringAppendElement(&str, pElem->markup.argv[j]);
        }
        Tcl_DStringEndSublist(&str);
        HtmlFree(pElem);
        HtmlLock(p);
        Tcl_GlobalEval(p->interp, Tcl_DStringValue(&str));
        Tcl_DStringFree(&str);
        if( HtmlUnlock(p) ){ return 0; }

        /* Tricky, tricky.  The callback might have caused the p->zText
        ** pointer to change, so renew our copy of that pointer.  The
        ** callback might also have cleared or destroyed the widget.
        ** If so, abort this routine.
        */
        z = p->zText;
        if( z==0 || p->tkwin==0 ){
          n = 0;
          iCol = 0;
          goto incomplete;
        }
        continue;
      }

      /* No special handler for this markup.  Just append it to the
      ** list of all tokens.
      */
      AppendElement(p,pElem);
      switch( pMap->type ){
        case Html_PLAINTEXT:
        case Html_LISTING:
        case Html_XMP:
        case Html_TEXTAREA:
          p->iPlaintext = pMap->type;
          break;
        case Html_STYLE:
        case Html_SCRIPT:
          p->pScript = (HtmlScript*)pElem;
          break;
        default:
          break;
      }

      /* If this is self-closing markup (ex: <br/> or <img/>) then
      ** synthesize a closing token.
      */
      if( selfClose && argv[0][0]!='/' 
      && strcmp(&pMap[1].zName[1],pMap->zName)==0 ){
        selfClose = 0;
        pMap++;
        argc = 1;
        goto makeMarkupEntry;
      }
    }
  }
incomplete:
  p->iCol = iCol;
  return n;
}
Esempio n. 16
0
/*
 *---------------------------------------------------------------------------
 *
 * HtmlImageTile --
 *
 * Results:
 *
 * Side effects:
 *     None.
 *
 *---------------------------------------------------------------------------
 */
Tk_Image 
HtmlImageTile(
    HtmlImage2 *pImage,    /* Image object */
    int *pW,
    int *pH
    )
{
    HtmlTree *pTree = pImage->pImageServer->pTree;
    Tcl_Interp *interp = pTree->interp;

    Tcl_Obj *pTileName;             /* Name of tile image at the script level */
    Tk_PhotoHandle tilephoto;       /* Photo of tile */
    Tk_PhotoImageBlock tileblock;   /* Block of tile image */
    int iTileWidth;
    int iTileHeight;

    Tk_PhotoHandle origphoto;
    Tk_PhotoImageBlock origblock;

    int x;
    int y;

    /* The tile has already been generated. Return it. */
    if (pImage->pTileName) {
        goto return_tile;
    }

    /* The image is too big to bother with a tile. Return the original. */
    if (!tilesize(pImage, &iTileWidth, &iTileHeight)) {
        goto return_original;
    }

    /* Retrieve the block for the original image */
    origphoto = Tk_FindPhoto(interp, Tcl_GetString(pImage->pImageName));
    if (!origphoto) goto return_original;
    Tk_PhotoGetImage(origphoto, &origblock);
    if (!origblock.pixelPtr) goto return_original;

    /* Create the tile image. Surely there is a way to do this without
     * invoking a script, but I haven't found it yet.
     */
    Tcl_Eval(interp, "image create photo");
    pTileName = Tcl_GetObjResult(interp);
    Tcl_IncrRefCount(pTileName);
    tilephoto = Tk_FindPhoto(interp, Tcl_GetString(pTileName));
    Tk_PhotoGetImage(tilephoto, &tileblock);
    pImage->pTileName = pTileName;
    pImage->tile = Tk_GetImage(
            interp, pTree->tkwin, Tcl_GetString(pTileName), imageChanged, 0
    );

    /* Allocate a block to write the tile data into. */
    tileblock.pixelPtr = (unsigned char *)HtmlAlloc(
        "temp", iTileWidth * iTileHeight * 4
    );
    tileblock.width = iTileWidth;
    tileblock.height = iTileHeight;
    tileblock.pitch = iTileWidth * 4;
    tileblock.pixelSize = 4;
    tileblock.offset[0] = 0;
    tileblock.offset[1] = 1;
    tileblock.offset[2] = 2;
    tileblock.offset[3] = 3;

    for (x = 0; x < iTileWidth; x++) {
        for (y = 0; y < iTileHeight; y++) {
            unsigned char *zOrig;
            unsigned char *zScale;
            zOrig = &origblock.pixelPtr[
                 (x % pImage->width) *origblock.pixelSize + 
                 (y % pImage->height) * origblock.pitch
            ];
            zScale = &tileblock.pixelPtr[x * 4 + y * tileblock.pitch];
            zScale[0] = zOrig[origblock.offset[0]];
            zScale[1] = zOrig[origblock.offset[1]];
            zScale[2] = zOrig[origblock.offset[2]];
            zScale[3] = zOrig[origblock.offset[3]];
        }
    }

    photoputblock(interp,tilephoto,&tileblock,0,0,iTileWidth,iTileHeight,0);
    HtmlFree(tileblock.pixelPtr);
    pImage->iTileWidth = iTileWidth;
    pImage->iTileHeight = iTileHeight;

return_tile:
    *pW = pImage->iTileWidth;
    *pH = pImage->iTileHeight;
    return pImage->tile;

return_original:
    HtmlImageSize(pImage, pW, pH);
    return HtmlImageImage(pImage);
}
Esempio n. 17
0
/*
** This routine adds information to the input texts that doesn't change
** when the display is resized or when new fonts are selected, etc.
** Mostly this means adding style attributes.  But other constant
** information (such as numbering on <li> and images used for <IMG>)
** is also obtained.  The key is that this routine is only called
** once, where the sizer and layout routines can be called many times.
**
** This routine is called whenever the list of elements grows.  The
** style stack is stored as part of the HTML widget so that we can
** always continue where we left off the last time.
**
** In addition to adding style, this routine will invoke callbacks
** needed to acquire information about a markup.  The htmlPtr->zIsVisitied
** callback is called for each <a> and the htmlPtr->zGetImage is called
** for each <IMG> or for each <LI> that has a SRC= field.
**
** This routine may invoke a callback procedure which could delete
** the HTML widget.
**
** When a markup is inserted or deleted from the token list, the
** style routine must be completely rerun from the beginning.  So
** what we said above, that this routine is only run once, is not
** strictly true.
*/
void HtmlAddStyle(HtmlWidget *htmlPtr, HtmlElement *p){
  HtmlStyle style;          /* Current style */
  int size;                 /* A new font size */
  int i;                    /* Loop counter */
  int paraAlign;            /* Current paragraph alignment */
  int rowAlign;             /* Current table row alignment */
  int anchorFlags;          /* Flags associated with <a> tag */
  int inDt;                 /* True if within <dt>..</dt> */
  HtmlStyle nextStyle;      /* Style for next token if useNextStyle==1 */
  int useNextStyle = 0;     /* True if nextStyle is valid */
  char *z;                  /* A tag parameter's value */

  /* The size of header fonts relative to the current font size */
  static int header_sizes[] = {+2, +1, 1, 1, -1, -1};

  /* Don't allow recursion */
  if( htmlPtr->flags & STYLER_RUNNING ){ TestPoint(0); return; }
  htmlPtr->flags |= STYLER_RUNNING;

  /* Load the style state out of the htmlPtr structure and into local
  ** variables.  This is purely a matter of convenience... */
  style = GetCurrentStyle(htmlPtr);
  paraAlign = htmlPtr->paraAlignment;
  rowAlign = htmlPtr->rowAlignment;
  anchorFlags = htmlPtr->anchorFlags;
  inDt = htmlPtr->inDt;

  /* Loop over tokens */
  while( p ){
    switch( p->base.type ){
      case Html_A:
        if( htmlPtr->anchorStart ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndA);
          htmlPtr->anchorStart = 0;
          anchorFlags = 0;
        }
        z = HtmlMarkupArg(p,"href",0);
        if( z ){
          HtmlLock(htmlPtr);
          style.color = GetLinkColor(htmlPtr, z);
          if( htmlPtr->underlineLinks ){
            style.flags |= STY_Underline;
          }
          if( HtmlUnlock(htmlPtr) ) return;
          anchorFlags |= STY_Anchor;
          PushStyleStack(htmlPtr, Html_EndA, style);
          htmlPtr->anchorStart = p;
        }
        break;
      case Html_EndA:
        if( htmlPtr->anchorStart ){
          p->ref.pOther = htmlPtr->anchorStart;
          style = HtmlPopStyleStack(htmlPtr, Html_EndA);
          htmlPtr->anchorStart = 0;
          anchorFlags = 0;
        }
        break;
      case Html_ADDRESS:
      case Html_EndADDRESS:
      case Html_BLOCKQUOTE:
      case Html_EndBLOCKQUOTE:
        paraAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_APPLET:
        if( htmlPtr->zAppletCommand && *htmlPtr->zAppletCommand ){
          nextStyle = style;
          nextStyle.flags |= STY_Invisible;
          PushStyleStack(htmlPtr, Html_EndAPPLET, nextStyle);
          useNextStyle = 1;
        }else{
          PushStyleStack(htmlPtr, Html_EndAPPLET, style);
        }
        TestPoint(0);
        break;
      case Html_B:
        style.font = BoldFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndB, style);
        TestPoint(0);
        break;
      case Html_EndAPPLET:
      case Html_EndB:
      case Html_EndBIG:
      case Html_EndCENTER:
      case Html_EndCITE:
      case Html_EndCODE:
      case Html_EndCOMMENT:
      case Html_EndEM:
      case Html_EndFONT:
      case Html_EndI:
      case Html_EndKBD:
      case Html_EndMARQUEE:
      case Html_EndNOBR:
      case Html_EndNOFRAME:
      case Html_EndNOSCRIPT:
      case Html_EndS:
      case Html_EndSAMP:
      case Html_EndSMALL:
      case Html_EndSTRIKE:
      case Html_EndSTRONG:
      case Html_EndSUB:
      case Html_EndSUP:
      case Html_EndTITLE:
      case Html_EndTT:
      case Html_EndU:
      case Html_EndVAR:
        style = HtmlPopStyleStack(htmlPtr, p->base.type);
        TestPoint(0);
        break;
      case Html_BASE:
        z = HtmlMarkupArg(p,"href",0);
        if( z ){
          HtmlLock(htmlPtr);
          z = HtmlResolveUri(htmlPtr, z);
          if( HtmlUnlock(htmlPtr) ) return;
          if( z!=0 ){
            if( htmlPtr->zBaseHref ){
              HtmlFree(htmlPtr->zBaseHref);
            }
            htmlPtr->zBaseHref = z;
          }
        }
        break;
      case Html_EndDIV:
        paraAlign = ALIGN_None;
        style = HtmlPopStyleStack(htmlPtr, p->base.type);
        TestPoint(0);
        break;
      case Html_EndBASEFONT:
        style = HtmlPopStyleStack(htmlPtr, Html_EndBASEFONT);
        style.font = FontFamily(style.font) + 2;
        TestPoint(0);
        break;
      case Html_BIG:
        ScaleFont(&style,1);
        PushStyleStack(htmlPtr, Html_EndBIG, style);
        TestPoint(0);
        break;
      case Html_CAPTION:
        paraAlign = GetAlignment(p, paraAlign);
        TestPoint(0);
        break;
      case Html_EndCAPTION:
        paraAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_CENTER:
        paraAlign = ALIGN_None;
        style.align = ALIGN_Center;
        PushStyleStack(htmlPtr, Html_EndCENTER, style);
        TestPoint(0);
        break;
      case Html_CITE:
        PushStyleStack(htmlPtr, Html_EndCITE, style);
        TestPoint(0);
        break;
      case Html_CODE:
        style.font = CWFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndCODE, style);
        TestPoint(0);
        break;
      case Html_COMMENT:
        style.flags |= STY_Invisible;
        PushStyleStack(htmlPtr, Html_EndCOMMENT, style);
        TestPoint(0);
        break;
      case Html_DD:
        if( htmlPtr->innerList && htmlPtr->innerList->base.type==Html_DL ){
          p->ref.pOther = htmlPtr->innerList;
          TestPoint(0);
        }else{
          p->ref.pOther = 0;
          TestPoint(0);
        }
        inDt = 0;
        break;
      case Html_DIR:
      case Html_MENU:
      case Html_UL:
        p->list.pPrev = htmlPtr->innerList;
        p->list.cnt = 0;
        htmlPtr->innerList = p;
        if( p->list.pPrev==0 ){
          p->list.type = LI_TYPE_Bullet1;
          p->list.compact = HtmlMarkupArg(p,"compact",0)!=0;
          TestPoint(0);
        }else if( p->list.pPrev->list.pPrev==0 ){
          p->list.type = LI_TYPE_Bullet2;
          p->list.compact = 1;
          TestPoint(0);
        }else{
          p->list.type = LI_TYPE_Bullet3;
          p->list.compact = 1;
          TestPoint(0);
        }
        p->list.type = GetUnorderedListType(p,p->list.type);
        break;
      case Html_EndDL:
        inDt = 0;
        TestPoint(0);
        /* Fall thru into the next case */
      case Html_EndDIR:
      case Html_EndMENU:
      case Html_EndOL:
      case Html_EndUL:
        p->ref.pOther = htmlPtr->innerList;
        if( htmlPtr->innerList ){
          htmlPtr->innerList = htmlPtr->innerList->list.pPrev;
          TestPoint(0);
        }else{
          TestPoint(0);
        }
        break;
      case Html_DIV:
        paraAlign = ALIGN_None;
        style.align = GetAlignment(p, style.align);
        PushStyleStack(htmlPtr, Html_EndDIV, style);
        TestPoint(0);
        break;
      case Html_DT:
        if( htmlPtr->innerList && htmlPtr->innerList->base.type==Html_DL ){
          p->ref.pOther = htmlPtr->innerList;
          TestPoint(0);
        }else{
          p->ref.pOther = 0;
          TestPoint(0);
        }
        inDt = STY_DT;
        break;
      case Html_EndDD:
      case Html_EndDT:
        inDt = 0;
        TestPoint(0);
        break;
      case Html_DL:
        p->list.pPrev = htmlPtr->innerList;
        p->list.cnt = 0;
        htmlPtr->innerList = p;
        p->list.compact = HtmlMarkupArg(p,"compact",0)!=0;
        inDt = 0;
        TestPoint(0);
        break;
      case Html_EM:
        style.font = ItalicFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndEM, style);
        TestPoint(0);
        break;
      case Html_EMBED:
        break;
      case Html_BASEFONT:
      case Html_FONT:
        z = HtmlMarkupArg(p,"size",0);
        if( z ){
          if( *z=='-' ){
            size = FontSize(style.font) - atoi(&z[1]);
          }else if( *z=='+' ){
            size = FontSize(style.font) + atoi(&z[1]);
          }else{
            size = atoi(z);
          }
          if( size <= 0 ){
            size = 1;
          }
          if( size >= N_FONT_SIZE ){
            size = N_FONT_SIZE - 1;
          }
          style.font = FontFamily(style.font) + size - 1;
        }
        z = HtmlMarkupArg(p,"color",0);
        if( z ){
          style.color = HtmlGetColorByName(htmlPtr, z);
        }
        PushStyleStack(htmlPtr,
            p->base.type==Html_FONT ? Html_EndFONT : Html_EndBASEFONT, style);
        break;
      case Html_FORM: {
        char *zUrl;
        char *zMethod;
        Tcl_DString cmd;      /* -formcommand callback */
        int result;
        char zToken[50];

        htmlPtr->formStart = 0;
        p->form.id = 0;
        if( htmlPtr->zFormCommand==0 || htmlPtr->zFormCommand[0]==0 ){
          TestPoint(0);
          break;
        }
        zUrl = HtmlMarkupArg(p,"action",0);
        if( zUrl==0 ){
          TestPoint(0);
          break;
        }
        HtmlLock(htmlPtr);
        zUrl = HtmlResolveUri(htmlPtr, zUrl);
        if( HtmlUnlock(htmlPtr) ) return;
        if( zUrl==0 ) break;
        zMethod = HtmlMarkupArg(p,"method","GET");
        sprintf(zToken," %d form ", ++htmlPtr->nForm);
        Tcl_DStringInit(&cmd);
        Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1);
        Tcl_DStringAppend(&cmd, zToken, -1);
        Tcl_DStringAppendElement(&cmd, zUrl);
        HtmlFree(zUrl);
        Tcl_DStringAppendElement(&cmd, zMethod);
        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) ) return;
        if( result==TCL_OK ){
          htmlPtr->formStart = p;
          p->form.id = htmlPtr->nForm;
        }
        Tcl_ResetResult(htmlPtr->interp);
        break;
      }
      case Html_EndFORM:
        p->ref.pOther = htmlPtr->formStart;
        htmlPtr->formStart = 0;
        TestPoint(0);
        break;
      case Html_H1:
      case Html_H2:
      case Html_H3:
      case Html_H4:
      case Html_H5:
      case Html_H6:
        paraAlign = ALIGN_None;
        i = (p->base.type - Html_H1)/2 + 1;
        if( i>=1 && i<=6 ){
          ScaleFont(&style,header_sizes[i-1]);
        }
        style.font = BoldFont( FontSize(style.font) );
        style.align = GetAlignment(p, style.align);
        PushStyleStack(htmlPtr, Html_EndH1, style);
        break;
      case Html_EndH1:
      case Html_EndH2:
      case Html_EndH3:
      case Html_EndH4:
      case Html_EndH5:
      case Html_EndH6:
        paraAlign = ALIGN_None;
        style = HtmlPopStyleStack(htmlPtr, Html_EndH1);
        TestPoint(0);
        break;
      case Html_HR:
        nextStyle = style;
        style.align = GetAlignment(p, ALIGN_None);
        useNextStyle = 1;
        break;
      case Html_I:
        style.font = ItalicFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndI, style);
        TestPoint(0);
        break;
      case Html_IMG:
        HtmlLock(htmlPtr);
        p->image.pImage = HtmlGetImage(htmlPtr, p);
        if( HtmlUnlock(htmlPtr) ) return;
        TestPoint(0);
        break;
      case Html_INPUT:
        p->input.pForm = htmlPtr->formStart;
        TestPoint(0);
        break;
      case Html_KBD:
        style.font = CWFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndKBD, style);
        TestPoint(0);
        break;
      case Html_LI:
        if( htmlPtr->innerList ){
          p->li.type = htmlPtr->innerList->list.type;
          if( htmlPtr->innerList->base.type==Html_OL ){
            z = HtmlMarkupArg(p, "value", 0);
            if( z ){
              int n = atoi(z);
              if( n>0 ){
                p->li.cnt = n;
                htmlPtr->innerList->list.cnt = n+1;
                TestPoint(0);
              }else{
                TestPoint(0);
              }
            }else{
              p->li.cnt = htmlPtr->innerList->list.cnt++;
              TestPoint(0);
            }
            p->li.type = GetOrderedListType(p,p->li.type);
          }else{
            p->li.type = GetUnorderedListType(p,p->li.type);
            TestPoint(0);
          }
        }else{
          p->base.flags &= ~HTML_Visible;
          TestPoint(0);
        }
        break;
      case Html_MARQUEE:
        style.flags |= STY_Invisible;
        PushStyleStack(htmlPtr, Html_EndMARQUEE, style);
        TestPoint(0);
        break;
      case Html_NOBR:
        style.flags |= STY_NoBreak;
        PushStyleStack(htmlPtr, Html_EndNOBR, style);
        TestPoint(0);
        break;
      case Html_NOFRAME:
        if( htmlPtr->zFrameCommand && *htmlPtr->zFrameCommand ){
          nextStyle = style;
          nextStyle.flags |= STY_Invisible;
          PushStyleStack(htmlPtr, Html_EndNOFRAME, nextStyle);
          useNextStyle = 1;
        }else{
          PushStyleStack(htmlPtr, Html_EndNOFRAME, style);
        }
        TestPoint(0);
        break;
      case Html_NOSCRIPT:
        if( htmlPtr->zScriptCommand && *htmlPtr->zScriptCommand ){
          nextStyle = style;
          nextStyle.flags |= STY_Invisible;
          PushStyleStack(htmlPtr, Html_EndNOSCRIPT, nextStyle);
          useNextStyle = 1;
        }else{
          PushStyleStack(htmlPtr, Html_EndNOSCRIPT, style);
        }
        TestPoint(0);
        break;
      case Html_OL:
        p->list.pPrev = htmlPtr->innerList;
        p->list.type = GetOrderedListType(p,LI_TYPE_Enum_1);
        p->list.cnt = 1;
        z = HtmlMarkupArg(p,"start",0);
        if( z ){
          int n = atoi(z);
          if( n>0 ){
            p->list.cnt = n;
            TestPoint(0);
          }else{
            TestPoint(0);
          }
        }else{
          TestPoint(0);
        }
        p->list.compact = htmlPtr->innerList!=0 ||
                          HtmlMarkupArg(p,"compact",0)!=0;
        htmlPtr->innerList = p;
        break;
      case Html_P:
        paraAlign = GetAlignment(p, ALIGN_None);
        TestPoint(0);
        break;
      case Html_EndP:
        paraAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_PRE:
      case Html_LISTING:
      case Html_XMP:
      case Html_PLAINTEXT:
        paraAlign = ALIGN_None;
        style.font = CWFont( FontSize(style.font) );
        style.flags |= STY_Preformatted;
        PushStyleStack(htmlPtr, Html_EndPRE, style);
        TestPoint(0);
        break;
      case Html_EndPRE:
      case Html_EndLISTING:
      case Html_EndXMP:
        style = HtmlPopStyleStack(htmlPtr, Html_EndPRE);
        TestPoint(0);
        break;
      case Html_S:
        style.flags |= STY_StrikeThru;
        PushStyleStack(htmlPtr, Html_EndS, style);
        TestPoint(0);
        break;
      case Html_SCRIPT:
        if( htmlPtr->zScriptCommand && *htmlPtr->zScriptCommand ){
          Tcl_DString cmd;
          int result;
          Tcl_DStringInit(&cmd);
          Tcl_DStringAppend(&cmd, htmlPtr->zScriptCommand, -1);
          Tcl_DStringStartSublist(&cmd);
          HtmlAppendArglist(&cmd, p);
          Tcl_DStringEndSublist(&cmd);
          Tcl_DStringStartSublist(&cmd);
          Tcl_DStringAppend(&cmd, p->script.zScript, p->script.nScript);
          Tcl_DStringEndSublist(&cmd);
          HtmlLock(htmlPtr);
          result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
          Tcl_DStringFree(&cmd);
          if( HtmlUnlock(htmlPtr) ) return;
          Tcl_ResetResult(htmlPtr->interp);
        }
        nextStyle = style;
        style.flags |= STY_Invisible;
        useNextStyle = 1;
        break;
      case Html_SELECT:
        p->input.pForm = htmlPtr->formStart;
        nextStyle.flags |= STY_Invisible;
        useNextStyle = 1;
        PushStyleStack(htmlPtr, Html_EndSELECT, style);
        htmlPtr->formElemStart = p;
        break;
      case Html_EndSELECT:
        style = HtmlPopStyleStack(htmlPtr, Html_EndSELECT);
        if( htmlPtr->formElemStart
        && htmlPtr->formElemStart->base.type==Html_SELECT ){
          p->ref.pOther = htmlPtr->formElemStart;
          MakeInvisible(p->ref.pOther, p);
        }else{
          p->ref.pOther = 0;
        }
        htmlPtr->formElemStart = 0;
        break;
      case Html_STRIKE:
        style.flags |= STY_StrikeThru;
        PushStyleStack(htmlPtr, Html_EndSTRIKE, style);
        TestPoint(0);
        break;
      case Html_STYLE:
        /* Ignore style sheets */
        break;
      case Html_SAMP:
        style.font = CWFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndSAMP, style);
        TestPoint(0);
        break;
      case Html_SMALL:
        ScaleFont(&style,-1);
        PushStyleStack(htmlPtr, Html_EndSMALL, style);
        TestPoint(0);
        break;
      case Html_STRONG:
        style.font = BoldFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndSTRONG, style);
        TestPoint(0);
        break;
      case Html_SUB:
        ScaleFont(&style,-1);
        if( style.subscript > -6 ){
          style.subscript--;
          TestPoint(0);
        }else{
          TestPoint(0);
        }
        PushStyleStack(htmlPtr, Html_EndSUB, style);
        break;
      case Html_SUP:
        ScaleFont(&style,-1);
        if( style.subscript < 6 ){
          style.subscript++;
          TestPoint(0);
        }else{
          TestPoint(0);
        }
        PushStyleStack(htmlPtr, Html_EndSUP, style);
        break;
      case Html_TABLE:
        paraAlign = ALIGN_None;
        nextStyle = style;
        nextStyle.align = ALIGN_Left;
        z = HtmlMarkupArg(p, "bgcolor", 0);
        if( z ){
          nextStyle.bgcolor = HtmlGetColorByName(htmlPtr, z);
          style.bgcolor = nextStyle.bgcolor;
/*        }else{
          nextStyle.bgcolor = COLOR_Background; */
        }
        PushStyleStack(htmlPtr, Html_EndTABLE, nextStyle);
        useNextStyle = 1;
        htmlPtr->inTd = 0;
        htmlPtr->inTr = 0;
        TestPoint(0);
        break;
      case Html_EndTABLE:
        paraAlign = ALIGN_None;
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
          htmlPtr->inTd = 0;
        }
        if( htmlPtr->inTr ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTR);
          htmlPtr->inTr = 0;
        }
        style = HtmlPopStyleStack(htmlPtr, p->base.type);
        TestPoint(0);
        break;
      case Html_TD:
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
        }
        htmlPtr->inTd = 1;
        paraAlign = GetAlignment(p, rowAlign);
        if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){
          style.bgcolor = HtmlGetColorByName(htmlPtr, z);
        }
        PushStyleStack(htmlPtr, Html_EndTD, style);
        TestPoint(0);
        break;
      case Html_TEXTAREA:
        p->input.pForm = htmlPtr->formStart;
        nextStyle = style;
        nextStyle.flags |= STY_Invisible;
        PushStyleStack(htmlPtr, Html_EndTEXTAREA, nextStyle);
        htmlPtr->formElemStart = p;
        useNextStyle = 1;
        TestPoint(0);
        break;
      case Html_EndTEXTAREA:
        style = HtmlPopStyleStack(htmlPtr, Html_EndTEXTAREA);
        if( htmlPtr->formElemStart
        && htmlPtr->formElemStart->base.type==Html_TEXTAREA ){
          p->ref.pOther = htmlPtr->formElemStart;
        }else{
          p->ref.pOther = 0;
        }
        htmlPtr->formElemStart = 0;
        break;
      case Html_TH:
        /* paraAlign = GetAlignment(p, rowAlign); */
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
        }
        paraAlign = GetAlignment(p, ALIGN_Center);
        style.font = BoldFont( FontSize(style.font) );
        if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){
          style.bgcolor = HtmlGetColorByName(htmlPtr, z);
        }
        PushStyleStack(htmlPtr, Html_EndTD, style);
        htmlPtr->inTd = 1;
        TestPoint(0);
        break;
      case Html_TR:
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
          htmlPtr->inTd = 0;
        }
        if( htmlPtr->inTr ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTR);
        }
        rowAlign = GetAlignment(p, ALIGN_None);
        if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){
          style.bgcolor = HtmlGetColorByName(htmlPtr, z);
        }
        PushStyleStack(htmlPtr, Html_EndTR, style);
        htmlPtr->inTr = 1;
        TestPoint(0);
        break;
      case Html_EndTR:
        if( htmlPtr->inTd ){
          style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
          htmlPtr->inTd = 0;
        }
        style = HtmlPopStyleStack(htmlPtr, Html_EndTR);
        htmlPtr->inTr = 0;
        paraAlign = ALIGN_None;
        rowAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_EndTD:
      case Html_EndTH:
        style = HtmlPopStyleStack(htmlPtr, Html_EndTD);
        htmlPtr->inTd = 0;
        paraAlign = ALIGN_None;
        rowAlign = ALIGN_None;
        TestPoint(0);
        break;
      case Html_TITLE:
        style.flags |= STY_Invisible;
        PushStyleStack(htmlPtr, Html_EndTITLE, style);
        TestPoint(0);
        break;
      case Html_TT:
        style.font = CWFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndTT, style);
        TestPoint(0);
        break;
      case Html_U:
        style.flags |= STY_Underline;
        PushStyleStack(htmlPtr, Html_EndU, style);
        break;
      case Html_VAR:
        style.font = ItalicFont( FontSize(style.font) );
        PushStyleStack(htmlPtr, Html_EndVAR, style);
        TestPoint(0);
        break;
      default:
        TestPoint(0);
        break;
    }
    p->base.style = style;
    p->base.style.flags |= anchorFlags | inDt;
    if( paraAlign!=ALIGN_None ){
      p->base.style.align = paraAlign;
    }
    if( useNextStyle ){
      style = nextStyle;
      useNextStyle = 0;
    }
    TRACE(HtmlTrace_Style,
      ("Style of 0x%08x font=%02d color=%02d bg=%02d "
       "align=%d flags=0x%04x token=%s\n",
      (int)p, p->base.style.font, p->base.style.color, p->base.style.bgcolor,
      p->base.style.align, p->base.style.flags, HtmlTokenName(p)));
    p = p->pNext;
  }

  /* Copy state information back into the htmlPtr structure for
  ** safe keeping. */
  htmlPtr->paraAlignment = paraAlign;
  htmlPtr->rowAlignment = rowAlign;
  htmlPtr->anchorFlags = anchorFlags;
  htmlPtr->inDt = inDt;
  htmlPtr->flags &= ~STYLER_RUNNING;
}
Esempio n. 18
0
/*
 *---------------------------------------------------------------------------
 *
 * HtmlImageServerGet --
 *
 *     Retrieve an HtmlImage2 object for the image at URL zUrl from 
 *     an image-server. The caller should match this call with a single
 *     HtmlImageFree() when the image object is no longer required.
 *
 *     If the image is not already in the cache, the Tcl script 
 *     configured as the widget -imagecmd is invoked. If this command
 *     raises an error or returns an invalid result, then this function 
 *     returns NULL. A Tcl back-ground error is propagated in this case 
 *     also.
 *
 * Results:
 *     Pointer to HtmlImage2 object containing the image from zUrl, or
 *     NULL, if zUrl was invalid for some reason.
 *
 * Side effects:
 *     May invoke -imagecmd script.
 *
 *---------------------------------------------------------------------------
 */
HtmlImage2 *
HtmlImageServerGet (HtmlImageServer *p, const char *zUrl) 
{
    Tcl_Obj *pImageCmd = p->pTree->options.imagecmd;
    Tcl_Interp *interp = p->pTree->interp;
    Tcl_HashEntry *pEntry = 0;
    HtmlImage2 *pImage = 0;

    /* Try to find the requested image in the hash table. */
    if (pImageCmd) {
        int new_entry;
        pEntry = Tcl_CreateHashEntry(&p->aImage, zUrl, &new_entry);
        if (new_entry) {
            Tcl_Obj *pEval;
            Tcl_Obj *pResult;
            int rc;
            int nObj;
            Tcl_Obj **apObj = 0;
            Tk_Image img;
           
	    /* The image could not be found in the hash table and an 
             * -imagecmd callback is configured. The callback script 
             * must be executed to obtain an image. Build up a script 
             * in pEval and execute it. Put the result in variable pResult.
             */
            pEval = Tcl_DuplicateObj(pImageCmd);
            Tcl_IncrRefCount(pEval);
            Tcl_ListObjAppendElement(interp, pEval, Tcl_NewStringObj(zUrl, -1));
            rc = Tcl_EvalObjEx(interp, pEval, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
            Tcl_DecrRefCount(pEval);
            if (rc != TCL_OK) {
                goto image_get_out;
            }
            pResult = Tcl_GetObjResult(interp);
    
            /* Read the result into array apObj. If the result was
             * not a valid Tcl list, return NULL and raise a background
             * error about the badly formed list.
             */
            rc = Tcl_ListObjGetElements(interp, pResult, &nObj, &apObj);
            if (rc != TCL_OK) {
                goto image_get_out;
            }
            if (nObj==0) {
                Tcl_DeleteHashEntry(pEntry);
                goto image_unavailable;
            }

            pImage = HtmlNew(HtmlImage2);
            if (nObj == 1 || nObj == 2) {
                img = Tk_GetImage(
                    interp, p->pTree->tkwin, Tcl_GetString(apObj[0]),
                    imageChanged, pImage
                );
            }
            if ((nObj != 1 && nObj != 2) || !img) {
                Tcl_ResetResult(interp);
                Tcl_AppendResult(interp,  "-imagecmd returned bad value", 0);
                HtmlFree(pImage);
                pImage = 0;
                goto image_get_out;
            }

            Tcl_SetHashValue(pEntry, (ClientData)pImage);
            Tcl_IncrRefCount(apObj[0]);
            pImage->pImageName = apObj[0];
            if (nObj == 2) {
                Tcl_IncrRefCount(apObj[1]);
                pImage->pDelete = apObj[1];
            }
            pImage->pImageServer = p;
            pImage->zUrl = Tcl_GetHashKey(&p->aImage, pEntry);
            pImage->image = img;
            Tk_SizeOfImage(pImage->image, &pImage->width, &pImage->height);
            pImage->isValid = 1;
            HtmlImagePixmap(pImage);
        }
    }

image_get_out:
    pImage = (HtmlImage2 *)(pEntry ? Tcl_GetHashValue(pEntry) : 0);
    HtmlImageRef(pImage);
    if (!pImage && pImageCmd) {
        Tcl_BackgroundError(interp);
        Tcl_ResetResult(interp);
        assert(pEntry);
        Tcl_DeleteHashEntry(pEntry);
    }

image_unavailable:
    return pImage;
}
Esempio n. 19
0
Tcl_Obj *HtmlXImageToImage(
    HtmlTree *pTree,
    XImage *pXImage,
    int w,
    int h
    )
{
    Tcl_Interp *interp = pTree->interp;

    Tcl_Obj *pImage;
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;
    int x;
    int y;
    unsigned long redmask, redshift;
    unsigned long greenmask, greenshift;
    unsigned long bluemask, blueshift;
    Visual *pVisual;

    Tcl_Eval(interp, "image create photo");
    pImage = Tcl_GetObjResult(interp);
    Tcl_IncrRefCount(pImage);

    block.pixelPtr = (unsigned char *)HtmlAlloc("temp", w * h * 4);
    block.width = w;
    block.height = h;
    block.pitch = w*4;
    block.pixelSize = 4;
    block.offset[0] = 0;
    block.offset[1] = 1;
    block.offset[2] = 2;
    block.offset[3] = 3;

    pVisual = Tk_Visual(pTree->tkwin);

    redmask = pVisual->red_mask;
    bluemask = pVisual->blue_mask;
    greenmask = pVisual->green_mask;
    for (redshift=0; !((redmask>>redshift)&0x000000001); redshift++);
    for (greenshift=0; !((greenmask>>greenshift)&0x00000001); greenshift++);
    for (blueshift=0; !((bluemask>>blueshift)&0x00000001); blueshift++);

    for (x=0; x<w; x++) {
        for (y=0; y<h; y++) {
            unsigned char *pOut;
            unsigned long pixel = XGetPixel(pXImage, x, y);

            pOut = &block.pixelPtr[x*block.pixelSize + y*block.pitch];
            pOut[0] = (pixel&redmask)>>redshift;
            pOut[1] = (pixel&greenmask)>>greenshift;
            pOut[2] = (pixel&bluemask)>>blueshift;
            pOut[3] = 0xFF;
        }
    }

    photo = Tk_FindPhoto(interp, Tcl_GetString(pImage));
    photoputblock(interp, photo, &block, 0, 0, w, h, 0);
    HtmlFree(block.pixelPtr);

    return pImage;
}
Esempio n. 20
0
void 
HtmlImageFree (HtmlImage2 *pImage)
{
    if (!pImage) {
        return;
    }

    assert(pImage->nRef > 0);
    pImage->nRef--;
    if (
        pImage->nRef == 0 && 
        (pImage->pUnscaled || !pImage->pImageServer->isSuspendGC)
    ) {
        /* The reference count for this structure has reached zero.
         * Really delete it. The assert() says that an original image
         * cannot be deleted before all of it's scaled copies.
         */
        assert(pImage->pUnscaled || 0 == pImage->pNext);

        freeImageCompressed(pImage);
        freeTile(pImage);
        if (pImage->pixmap) {
            HtmlTree *pTree = pImage->pImageServer->pTree;
            Tk_FreePixmap(Tk_Display(pTree->tkwin), pImage->pixmap);
            pImage->pixmap = 0;
        }
        if (pImage->image) {
            Tk_FreeImage(pImage->image);
        }
        if (pImage->pImageName) {
            Tcl_Interp *interp = pImage->pImageServer->pTree->interp;
            Tcl_Obj *pEval;
            if (!pImage->pDelete) {
                pEval = Tcl_NewStringObj("image delete", -1);
                Tcl_IncrRefCount(pEval);
            } else {
                pEval = pImage->pDelete;
            }
            Tcl_ListObjAppendElement(interp, pEval, pImage->pImageName);
            Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
            Tcl_DecrRefCount(pEval);
            Tcl_DecrRefCount(pImage->pImageName);
        }

        if (pImage->pUnscaled) {
            HtmlImage2 *pIter;
            for (
                pIter = pImage->pUnscaled; 
                pIter->pNext != pImage; 
                pIter = pIter->pNext
            ) {
                assert(pIter->pNext);
            }
            pIter->pNext = pIter->pNext->pNext;
            HtmlImageFree(pImage->pUnscaled);
        } else {
            const char *zKey = pImage->zUrl;
            Tcl_HashTable *paImage = &pImage->pImageServer->aImage;
            Tcl_HashEntry *pEntry = Tcl_FindHashEntry(paImage, zKey);
            assert(pEntry);
            Tcl_DeleteHashEntry(pEntry);
        }

        HtmlFree(pImage);
        Tcl_CancelIdleCall(asyncPixmapify, (ClientData)pImage);
    }
}
Esempio n. 21
0
/*
** This routine implements the Sizer() function for <INPUT>,
** <SELECT> and <TEXTAREA> markup.
**
** A side effect of sizing these markups is that widgets are
** created to represent the corresponding input controls.
**
** The function normally returns 0.  But if it is dealing with
** a <SELECT> or <TEXTAREA> that is incomplete, 1 is returned.
** In that case, the sizer will be called again at some point in
** the future when more information is available.
*/
int HtmlControlSize(HtmlWidget *htmlPtr, HtmlElement *pElem){
  char *zWin;            /* Name of child widget that implements this input */
  int incomplete = 0;    /* True if data is incomplete */
  Tcl_DString cmd;       /* The complete -formcommand callback */
 
  if( pElem->input.sized ) return 0;
  pElem->input.type = InputType(pElem);
  switch( pElem->input.type ){
    case INPUT_TYPE_Checkbox:
    case INPUT_TYPE_Hidden:
    case INPUT_TYPE_Image:
    case INPUT_TYPE_Radio:
    case INPUT_TYPE_Reset:
    case INPUT_TYPE_Submit:
    case INPUT_TYPE_Text:
    case INPUT_TYPE_Password:
    case INPUT_TYPE_File: {
      int result;
      char zToken[50];

      if( pElem->input.pForm==0 || htmlPtr->zFormCommand==0 
           || htmlPtr->zFormCommand[0]==0 ){
        EmptyInput(pElem);
        break;
      }
      Tcl_DStringInit(&cmd);
      Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1);
      sprintf(zToken," %d input ",pElem->input.pForm->form.id);
      Tcl_DStringAppend(&cmd, zToken, -1);
      pElem->input.cnt = ++htmlPtr->nInput;
      zWin = MakeWindowName(htmlPtr, pElem);
      Tcl_DStringAppend(&cmd, zWin, -1);
      Tcl_DStringStartSublist(&cmd);
      HtmlAppendArglist(&cmd, pElem);
      Tcl_DStringEndSublist(&cmd);
      HtmlLock(htmlPtr);
      result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
      Tcl_DStringFree(&cmd);
      if( !HtmlUnlock(htmlPtr) ){
        SizeAndLink(htmlPtr, zWin, pElem);
      }
      HtmlFree(zWin);
      break;
    }
    case INPUT_TYPE_Select: {
      int result;
      char zToken[50];

      if( pElem->input.pForm==0 || htmlPtr->zFormCommand==0 
           || htmlPtr->zFormCommand[0]==0 ){
        EmptyInput(pElem);
        break;
      }
      Tcl_DStringInit(&cmd);
      Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1);
      sprintf(zToken," %d select ",pElem->input.pForm->form.id);
      Tcl_DStringAppend(&cmd, zToken, -1);
      pElem->input.cnt = ++htmlPtr->nInput;
      zWin = MakeWindowName(htmlPtr, pElem);
      Tcl_DStringAppend(&cmd, zWin, -1);
      Tcl_DStringStartSublist(&cmd);
      HtmlAppendArglist(&cmd, pElem);
      Tcl_DStringEndSublist(&cmd);
      Tcl_DStringStartSublist(&cmd);
      AddSelectOptions(&cmd, pElem, pElem->input.pEnd);
      Tcl_DStringEndSublist(&cmd);
      HtmlLock(htmlPtr);
      result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
      Tcl_DStringFree(&cmd);
      if( !HtmlUnlock(htmlPtr) ){
        SizeAndLink(htmlPtr, zWin, pElem);
      }
      HtmlFree(zWin);
      break;
    }
    case INPUT_TYPE_TextArea: {
      int result;
      char zToken[50];

      if( pElem->input.pForm==0 || htmlPtr->zFormCommand==0 
           || htmlPtr->zFormCommand[0]==0 ){
        EmptyInput(pElem);
        break;
      }
      Tcl_DStringInit(&cmd);
      Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1);
      sprintf(zToken," %d textarea ",pElem->input.pForm->form.id);
      Tcl_DStringAppend(&cmd, zToken, -1);
      pElem->input.cnt = ++htmlPtr->nInput;
      zWin = MakeWindowName(htmlPtr, pElem);
      Tcl_DStringAppend(&cmd, zWin, -1);
      Tcl_DStringStartSublist(&cmd);
      HtmlAppendArglist(&cmd, pElem);
      Tcl_DStringEndSublist(&cmd);
      Tcl_DStringStartSublist(&cmd);
      HtmlAppendText(&cmd, pElem, pElem->input.pEnd);
      Tcl_DStringEndSublist(&cmd);
      HtmlLock(htmlPtr);
      result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
      Tcl_DStringFree(&cmd);
      if( !HtmlUnlock(htmlPtr) ){
        SizeAndLink(htmlPtr, zWin, pElem);
      }
      HtmlFree(zWin);
      break;
    }
    case INPUT_TYPE_Applet: {
      int result;

      if( htmlPtr->zAppletCommand==0 || htmlPtr->zAppletCommand[0]==0 ){
        EmptyInput(pElem);
        break;
      }
      Tcl_DStringInit(&cmd);
      Tcl_DStringAppend(&cmd, htmlPtr->zAppletCommand, -1);
      Tcl_DStringAppend(&cmd, " ", 1);
      pElem->input.cnt = ++htmlPtr->nInput;
      zWin = MakeWindowName(htmlPtr, pElem);
      Tcl_DStringAppend(&cmd, zWin, -1);
      Tcl_DStringStartSublist(&cmd);
      HtmlAppendArglist(&cmd, pElem);
      Tcl_DStringEndSublist(&cmd);
      HtmlLock(htmlPtr);
      result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
      Tcl_DStringFree(&cmd);
      if( !HtmlUnlock(htmlPtr) ){
        SizeAndLink(htmlPtr, zWin, pElem);
      }
      HtmlFree(zWin);
      break;
    }
    default: {
      CANT_HAPPEN;
      pElem->base.flags &= ~HTML_Visible;
      pElem->base.style.flags |= STY_Invisible;
      pElem->input.tkwin = 0;
      break;
    }
  }
  return incomplete;
}