Esempio n. 1
0
/*
** Advance the layout as far as possible
*/
void HtmlLayout(HtmlWidget *htmlPtr){
  HtmlLayoutContext *pLC;
  int btm;

  if( htmlPtr->pFirst==0 ) return;
  HtmlLock(htmlPtr);
  HtmlSizer(htmlPtr);
  if( HtmlUnlock(htmlPtr) ) return;
  pLC = &htmlPtr->layoutContext;
  pLC->htmlPtr = htmlPtr;
  pLC->pageWidth = htmlPtr->realWidth - 2*(htmlPtr->inset + htmlPtr->padx);
  pLC->left = 0;
  pLC->right = 0;
  pLC->pStart = htmlPtr->nextPlaced;
  if( pLC->pStart==0 ){
    pLC->pStart = htmlPtr->pFirst;
  }
  if( pLC->pStart ){
    pLC->maxX = htmlPtr->maxX;
    pLC->maxY = htmlPtr->maxY;
    btm = pLC->bottom;
    HtmlLock(htmlPtr);
    HtmlLayoutBlock(pLC);
    if( HtmlUnlock(htmlPtr) ) return;
    htmlPtr->maxX = pLC->maxX;
    htmlPtr->maxY = pLC->maxY;
    htmlPtr->nextPlaced = pLC->pStart;
    htmlPtr->flags |= HSCROLL | VSCROLL;
    HtmlRedrawText(htmlPtr, btm);
  }
}
Esempio n. 2
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. 3
0
/*
** Delete all input controls.  This happens when the HTML widget
** is cleared.
**
** When the TCL "exit" command is invoked, the order of operations
** here is very touchy.  
*/
void HtmlDeleteControls(HtmlWidget *htmlPtr){
  HtmlElement *p;        /* For looping over all controls */
  Tcl_Interp *interp;    /* The interpreter */
  
  interp = htmlPtr->interp;
  p = htmlPtr->firstInput;
  htmlPtr->firstInput = 0;
  htmlPtr->lastInput = 0;
  htmlPtr->nInput = 0;
  if( p==0 || htmlPtr->tkwin==0 ) return;
  HtmlLock(htmlPtr);
  for(; p; p=p->input.pNext){
    if( p->input.pForm && p->input.pForm->form.id>0 
         && htmlPtr->zFormCommand && htmlPtr->zFormCommand[0]
         && !Tcl_InterpDeleted(interp) && htmlPtr->clipwin ){
      Tcl_DString cmd;
      int result;
      char zBuf[60];
      Tcl_DStringInit(&cmd);
      Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1);
      sprintf(zBuf," %d flush", p->input.pForm->form.id);
      Tcl_DStringAppend(&cmd, zBuf, -1);
      result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
      Tcl_DStringFree(&cmd);
      if( !Tcl_InterpDeleted(interp) ){
        if( result != TCL_OK ){
          Tcl_AddErrorInfo(htmlPtr->interp,
             "\n    (-formcommand flush callback executed by html widget)");
          Tcl_BackgroundError(htmlPtr->interp);
          TestPoint(0);
        }
        Tcl_ResetResult(htmlPtr->interp);
      }
      p->input.pForm->form.id = 0;
    }
    if( p->input.tkwin ){
      if( htmlPtr->clipwin!=0 ) Tk_DestroyWindow(p->input.tkwin);
      p->input.tkwin = 0;
    }
    p->input.sized = 0;
  }
  HtmlUnlock(htmlPtr);
}
Esempio n. 4
0
/*
** This is a convenient wrapper routine for HtmlCallResolver.
** It makes a copy of the result into memory obtained from HtmlAlloc()
** and invokes Tcl_ResetResult().
*/
char *HtmlResolveUri(HtmlWidget *htmlPtr, char *zUri){
  char *azSeq[2];
  char *zSrc;
  int result;

  if( zUri==0 || *zUri==0 ) return 0;
  azSeq[0] = zUri;
  azSeq[1] = 0;
  HtmlLock(htmlPtr);
  result = HtmlCallResolver(htmlPtr, azSeq);
  if( HtmlUnlock(htmlPtr) ) return 0;
  if( result==TCL_OK ){
    zSrc = HtmlAlloc( strlen(htmlPtr->interp->result) + 1 );
    if( zSrc ) strcpy(zSrc, htmlPtr->interp->result);
  }else{
    zSrc = 0;
  }
  Tcl_ResetResult(htmlPtr->interp);
  return zSrc;
}
Esempio n. 5
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. 6
0
/*
** Compute the size of all elements in the widget.  Assume that a
** style has already been assigned to all elements.
**
** Some of the elements might have already been sized.  Refer to the
** htmlPtr->lastSized and only compute sizes for elements that follow
** this one.  If htmlPtr->lastSized==0, then size everything.
**
** This routine only computes the sizes of individual elements.  The
** size of aggregate elements (like tables) are computed separately.
**
** The HTML_Visible flag is also set on every element that results
** in ink on the page.
**
** This routine may invoke a callback procedure which could delete
** the HTML widget.
*/
void HtmlSizer(HtmlWidget *htmlPtr){
  HtmlElement *p;
  int iFont = -1;
  Tk_Font font;
  int spaceWidth = 0;
  Tk_FontMetrics fontMetrics;
  char *z;
  int stop = 0;

  if( htmlPtr->pFirst==0 ){ TestPoint(0); return; }
  if( htmlPtr->lastSized==0 ){
    p = htmlPtr->pFirst;
    TestPoint(0);
  }else{
    p = htmlPtr->lastSized->pNext;
    TestPoint(0);
  }
  for(; !stop && p; p=p->pNext){
    if( p->base.style.flags & STY_Invisible ){
      p->base.flags &= ~HTML_Visible;
      TestPoint(0);
      continue;
    }
    if( iFont != p->base.style.font ){
      iFont = p->base.style.font;
      HtmlLock(htmlPtr);
      font = HtmlGetFont(htmlPtr, iFont);
      if( HtmlUnlock(htmlPtr) ) break;
      Tk_GetFontMetrics(font, &fontMetrics);
      spaceWidth = 0;
    }
    switch( p->base.type ){
      case Html_Text:
        p->text.w = Tk_TextWidth(font, p->text.zText, p->base.count);
        p->base.flags |= HTML_Visible;
        p->text.descent = fontMetrics.descent;
        p->text.ascent = fontMetrics.ascent;
        if( spaceWidth==0 ){
          spaceWidth = Tk_TextWidth(font, " ", 1);
          TestPoint(0);
        }else{
          TestPoint(0);
        }
        p->text.spaceWidth = spaceWidth;
        break;
      case Html_Space:
        if( spaceWidth==0 ){
          spaceWidth = Tk_TextWidth(font, " ", 1);
        }
        p->space.w = spaceWidth;
        p->space.descent = fontMetrics.descent;
        p->space.ascent = fontMetrics.ascent;
        p->base.flags &= ~HTML_Visible;
        break;
      case Html_TD:
      case Html_TH:
        z = HtmlMarkupArg(p, "rowspan","1");
        p->cell.rowspan = atoi(z);
        z = HtmlMarkupArg(p, "colspan","1");
        p->cell.colspan = atoi(z);
        p->base.flags |= HTML_Visible;
        TestPoint(0);
        break;
      case Html_LI:
        p->li.descent = fontMetrics.descent;
        p->li.ascent = fontMetrics.ascent;
        p->base.flags |= HTML_Visible;
        TestPoint(0);
        break;
      case Html_IMG:
        p->base.flags |= HTML_Visible;
        p->image.redrawNeeded = 0;
        p->image.textAscent = fontMetrics.ascent;
        p->image.textDescent = fontMetrics.descent;
        p->image.align = HtmlGetImageAlignment(p);
        if( p->image.pImage==0 ){
          p->image.ascent = fontMetrics.ascent;
          p->image.descent = fontMetrics.descent;
          p->image.zAlt = HtmlMarkupArg(p, "alt", "<image>");
          p->image.w = Tk_TextWidth(font, p->image.zAlt, strlen(p->image.zAlt));
        }else{
          int w, h;
          p->image.pNext = p->image.pImage->pList;
          p->image.pImage->pList = p;
          Tk_SizeOfImage(p->image.pImage->image, &w, &h);
          p->image.h = h;
          p->image.w = w;
          p->image.ascent = h/2;
          p->image.descent = h - p->image.ascent;
        }
        if( (z = HtmlMarkupArg(p, "width", 0))!=0 ){
          int w = atoi(z);
          if( w>0 ) p->image.w = w;
        }
        if( (z = HtmlMarkupArg(p, "height", 0))!=0 ){
          int h = atoi(z);
          if( h>0 ) p->image.h = h;
        }
        break;
      case Html_HR:
      case Html_TABLE:
        p->base.flags |= HTML_Visible;
        TestPoint(0);
        break;
      case Html_APPLET:
      case Html_EMBED:
      case Html_INPUT:
        p->input.textAscent = fontMetrics.ascent;
        p->input.textDescent = fontMetrics.descent;
        stop = HtmlControlSize(htmlPtr, p);
        break;
      case Html_SELECT:
      case Html_TEXTAREA:
        p->input.textAscent = fontMetrics.ascent;
        p->input.textDescent = fontMetrics.descent;
        break;
      case Html_EndSELECT:
      case Html_EndTEXTAREA:
        if( p->ref.pOther ){
          p->ref.pOther->input.pEnd = p;
          stop = HtmlControlSize(htmlPtr, p->ref.pOther);
        }
        break;
      default:
        p->base.flags &= ~HTML_Visible;
        break;
    }
  }
  if( p ){
    htmlPtr->lastSized = p;
  }else{
    htmlPtr->lastSized = htmlPtr->pLast;
  }
}
Esempio n. 7
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. 8
0
/*
** Display a single HtmlBlock.  This is where all the drawing
** happens.
*/
void HtmlBlockDraw(
  HtmlWidget *htmlPtr,   /* The main HTML widget */
  HtmlBlock *pBlock,     /* Block which needs to be drawn */
  Drawable drawable,     /* Draw the line on this */
  int drawableLeft,      /* Virtual coordinate of left edge of drawable */
  int drawableTop,       /* Virtual coordinate of top edge of drawable */
  int drawableWidth,     /* Width of the drawable */
  int drawableHeight     /* Height of the drawable */
){
  Tk_Font font;           /* Font to use to render text */
  GC gc;                  /* A graphics context */
  HtmlElement *src;       /* HtmlElement holding style information */
  HtmlElement *pTable;    /* The table (when drawing part of a table) */
  int x, y;               /* Where to draw */

  if( pBlock==0 ){ TestPoint(0); return; }
  src = pBlock->base.pNext;
  while( src && (src->base.flags & HTML_Visible)==0 ){
    src = src->base.pNext;
    TestPoint(0);
  }
  if( src==0 ){ TestPoint(0); return; }
  if( pBlock->n>0 ){
    /* We must be dealing with plain old text */
    if( src->base.type==Html_Text ){
      x = src->text.x;
      y = src->text.y;
      TestPoint(0);
    }else{
      CANT_HAPPEN;
      return;
    }
    if( pBlock->base.flags & HTML_Selected ){
      HtmlLock(htmlPtr);
      DrawSelectionBackground(htmlPtr, pBlock, drawable, 
                              drawableLeft, drawableTop);
      if( HtmlUnlock(htmlPtr) ) return;
    }
    gc = HtmlGetGC(htmlPtr, src->base.style.color, src->base.style.font);
    font = HtmlGetFont(htmlPtr, src->base.style.font);
    if( font==0 ) return;
    Tk_DrawChars(htmlPtr->display,
                 drawable,
                 gc, font,
                 pBlock->z, pBlock->n,
                 x - drawableLeft, y - drawableTop);
    if( src->base.style.flags & STY_Underline ){
      Tk_UnderlineChars(htmlPtr->display, drawable, gc, font, pBlock->z,
                        x - drawableLeft, y-drawableTop, 0, pBlock->n);
    }
    if( src->base.style.flags & STY_StrikeThru ){
      XRectangle xrec;
      xrec.x = pBlock->left - drawableLeft;
      xrec.y = (pBlock->top + pBlock->bottom)/2 - drawableTop;
      xrec.width = pBlock->right - pBlock->left;
      xrec.height = 1 + (pBlock->bottom - pBlock->top > 15);
      XFillRectangles(htmlPtr->display, drawable, gc, &xrec, 1);
    }
    if( pBlock==htmlPtr->pInsBlock && htmlPtr->insStatus>0 ){
      int x;
      XRectangle xrec;
      if( htmlPtr->insIndex < pBlock->n ){
        x = src->text.x - drawableLeft;
        x += Tk_TextWidth(font, pBlock->z, htmlPtr->insIndex);
      }else{
        x = pBlock->right - drawableLeft;
      }
      if( x>0 ){ TestPoint(0); x--; }
      xrec.x = x;
      xrec.y = pBlock->top - drawableTop;
      xrec.width =  2;
      xrec.height = pBlock->bottom - pBlock->top;
      XFillRectangles(htmlPtr->display, drawable, gc, &xrec, 1);
    }
  }else{
    /* We are dealing with a single HtmlElement which contains something
    ** other than plain text. */
    int top, btm, cntr;
    int cnt, w;
    char zBuf[30];
    switch( src->base.type ){
      case Html_LI:
        x = src->li.x;
        y = src->li.y;
        cntr = (top+btm)/2;
        switch( src->li.type ){
          case LI_TYPE_Enum_1:
            sprintf(zBuf,"%d.",src->li.cnt);
            TestPoint(0);
            break;
          case LI_TYPE_Enum_A:
            GetLetterIndex(zBuf,src->li.cnt,1);
            TestPoint(0);
            break;
          case LI_TYPE_Enum_a:
            GetLetterIndex(zBuf,src->li.cnt,0);
            TestPoint(0);
            break;
          case LI_TYPE_Enum_I:
            GetRomanIndex(zBuf,src->li.cnt,1);
            TestPoint(0);
            break;
          case LI_TYPE_Enum_i:
            GetRomanIndex(zBuf,src->li.cnt,0);
            TestPoint(0);
            break;
          default:
            zBuf[0] = 0;
            TestPoint(0);
            break;
        }
        gc = HtmlGetGC(htmlPtr, src->base.style.color, src->base.style.font);
        switch( src->li.type ){
          case LI_TYPE_Undefined:
          case LI_TYPE_Bullet1:
            XFillArc(htmlPtr->display,
                     drawable,
                     gc,
                     x - 7 - drawableLeft, y - 8 - drawableTop, 7, 7,
                     0, 360*64);
            TestPoint(0);
            break;

          case LI_TYPE_Bullet2:
            XDrawArc(htmlPtr->display,
                     drawable,
                     gc,
                     x - 7 - drawableLeft, y - 8 - drawableTop, 7, 7,
                     0, 360*64);
            TestPoint(0);
            break;

          case LI_TYPE_Bullet3:
            XDrawRectangle(htmlPtr->display,
                     drawable,
                     gc,
                     x - 7 - drawableLeft, y - 8 - drawableTop, 7, 7);
            TestPoint(0);
            break;
          
          case LI_TYPE_Enum_1:
          case LI_TYPE_Enum_A:
          case LI_TYPE_Enum_a:
          case LI_TYPE_Enum_I:
          case LI_TYPE_Enum_i:
            cnt = strlen(zBuf);
            font = HtmlGetFont(htmlPtr, src->base.style.font);
            if( font==0 ) return;
            w = Tk_TextWidth(font, zBuf, cnt);
            Tk_DrawChars(htmlPtr->display,
                 drawable,
                 gc, font,
                 zBuf, cnt, 
                 x - w - drawableLeft, y - drawableTop);
            TestPoint(0);
            break;
        }
        break;
      case Html_HR: {
        int relief = htmlPtr->ruleRelief;
        switch( relief ){
          case TK_RELIEF_RAISED: 
          case TK_RELIEF_SUNKEN:
            break;
          default:
            relief = TK_RELIEF_FLAT;
            break;
        }
        HtmlDrawRect(htmlPtr, drawable, src,
            src->hr.x - drawableLeft,
            src->hr.y - drawableTop,
            src->hr.w,
            src->hr.h,
            1, relief);
        break;
      }
      case Html_TABLE: {
        int relief = htmlPtr->tableRelief;
        switch( relief ){
          case TK_RELIEF_RAISED: 
          case TK_RELIEF_SUNKEN:
            break;
          default:
            relief = TK_RELIEF_FLAT;
            break;
        }
        HtmlDrawRect(htmlPtr, drawable, src,
                           src->table.x - drawableLeft,
                           src->table.y - drawableTop,
                           src->table.w, 
                           src->table.h,
                           src->table.borderWidth,
                           relief);
        break;
      }
      case Html_TH:
      case Html_TD: {
        int depth, relief;
        pTable = src->cell.pTable;
        depth = pTable && pTable->table.borderWidth>0;
        switch( htmlPtr->tableRelief ){
          case TK_RELIEF_RAISED:  relief = TK_RELIEF_SUNKEN; break;
          case TK_RELIEF_SUNKEN:  relief = TK_RELIEF_RAISED; break;
          default:                relief = TK_RELIEF_FLAT;   break;
        }
        HtmlDrawRect(htmlPtr, drawable, src,
                         src->cell.x - drawableLeft,
                         src->cell.y - drawableTop,
                         src->cell.w, 
                         src->cell.h,
                         depth,
                         relief);
        break;
      }
      case Html_IMG:
        if( src->image.pImage ){
          HtmlDrawImage(src, drawable, drawableLeft, drawableTop,
                        drawableLeft + drawableWidth,
                        drawableTop + drawableHeight);
        }else if( src->image.zAlt ){
          gc = HtmlGetGC(htmlPtr, src->base.style.color, src->base.style.font);
          font = HtmlGetFont(htmlPtr, src->base.style.font);
          if( font==0 ) return;
          Tk_DrawChars(htmlPtr->display,
                 drawable,
                 gc, font,
                 src->image.zAlt, strlen(src->image.zAlt),
                 src->image.x - drawableLeft, 
                 src->image.y - drawableTop);
          TestPoint(0);
        }    
        break;
      default:
        TestPoint(0);
        break;
    }
  }
}
Esempio n. 9
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. 10
0
/*
** Given a base index name (without any modifiers) return a pointer
** to the token described, and the character within that token.
**
** Valid input forms include:
**
**       N.M          Token number N (with numbering starting at 1) and
**                    character number M (with numbering starting at 0).
**
**       end          The end of all text
**
**       N.last       Last character of token number N.
**
**       sel.first    First character of the selection.
**
**       sel.last     Last character of the selection.
**
**       ins          The character holding the insertion cursor.
**
**       @X,Y         The character a location X,Y of the clipping window.
**
** Zero is returned if we are successful and non-zero if there is
** any kind of error.
**
** If the given token doesn't exist (for example if there are only 10
** tokens and 11.5 is requested) then *ppToken is left pointing to NULL.
** But the function still returns 0 for success.
*/
static int DecodeBaseIndex(
  HtmlWidget *htmlPtr,     /* The HTML widget we are dealing with */
  const char *zBase,       /* The base index string */
  HtmlElement **ppToken,   /* Write the pointer to the token here */
  int *pIndex              /* Write the character offset here */
){
  int x, y;
  int n;
  int i;
  HtmlElement *p;
  HtmlBlock *pBlock;
  HtmlBlock *pNearby;
  int dist = 1000000;
  int rc = 0;

  while( isspace(*zBase) ){ TestPoint(0); zBase++; }
  switch( *zBase ){
    case '1': case '2': case '3': case '4': case '5':
    case '6': case '7': case '8': case '9':
      n = sscanf(zBase,"%d.%d",&x,&y);
      if( n>0 ){
        p = *ppToken = HtmlTokenByIndex(htmlPtr, x, 0);
        TestPoint(0);
      }else{
        TestPoint(0);
      }
      if( n==2 ){
        *pIndex = y;
        TestPoint(0);
      }else{
        for(i=1; isdigit(zBase[i]); i++){ TestPoint(0); }
        if( zBase[i]==0 ){
          *pIndex = 0;
          TestPoint(0);
        }else if( strcmp(&zBase[i],".last")==0 ){
          maxIndex(p,pIndex);
          TestPoint(0);
        }else{
          rc = 1;
          TestPoint(0);
        }
      }
      break;
    case 'e':
      if( strcmp(zBase,"end")==0 ){
        p = *ppToken = htmlPtr->pLast;
        maxIndex(p,pIndex);
        TestPoint(0);
      }else{
        rc = 1;
        TestPoint(0);
      }
      break;
    case 's':
      if( strcmp(zBase,"sel.first")==0 ){
        *ppToken = htmlPtr->selBegin.p;
        *pIndex = htmlPtr->selBegin.i;
        TestPoint(0);
      }else if( strcmp(zBase,"sel.last")==0 ){
        *ppToken = htmlPtr->selEnd.p;
        *pIndex = htmlPtr->selEnd.i;
        TestPoint(0);
      }else{
        rc = 1;
        TestPoint(0);
      }
      break;
    case 'i':
      if( strcmp(zBase,"insert")==0 ){
        *ppToken = htmlPtr->ins.p;
        *pIndex = htmlPtr->ins.i;
        TestPoint(0);
      }else{
        rc = 1;
        TestPoint(0);
      }
      break;
    case '@':
      n = sscanf(zBase,"@%d,%d",&x,&y);
      if( n!=2 ){
        rc = 1;
        TestPoint(0);
        break;
      }
      x += htmlPtr->xOffset;
      y += htmlPtr->yOffset;
      pNearby = 0;
      *ppToken = htmlPtr->pLast;
      *pIndex = 0;
      for(pBlock=htmlPtr->firstBlock; pBlock; pBlock=pBlock->pNext){
        int dotest;
        if( pBlock->n==0 ){
          switch( pBlock->base.pNext->base.type ){
            case Html_LI:
            case Html_IMG:
            case Html_INPUT:
            case Html_TEXTAREA:
            case Html_SELECT:
              dotest = 1;
              TestPoint(0);
              break;
            default:
              dotest = 0;
              TestPoint(0);
              break;
          }
        }else{
          dotest = 1;
          TestPoint(0);
        }
        if (dotest){ 
          if( pBlock->top <= y && pBlock->bottom >= y ){
            if( pBlock->left > x ){
              if( pBlock->left - x < dist ){
                dist = pBlock->left - x;
                pNearby = pBlock;
                TestPoint(0);
              }else{
                TestPoint(0);
              }
            }else if( pBlock->right < x ){
              if( x - pBlock->right < dist ){
                dist = x - pBlock->right;
                pNearby = pBlock;
                TestPoint(0);
              }else{
                TestPoint(0);
              }
            }else{
              HtmlLock(htmlPtr);
              FindIndexInBlock(htmlPtr, pBlock, x, ppToken, pIndex);
              if( HtmlUnlock(htmlPtr) ) return 1;
              TestPoint(0);
              break;
            }
          }else{
            int distY;
            int distX;

            if( pBlock->bottom < y ){
              distY = y - pBlock->bottom;
              TestPoint(0);
            }else{
              distY = pBlock->top - y;
              TestPoint(0);
            }
            if( pBlock->left > x ){
              distX = pBlock->left - x;
              TestPoint(0);
            }else if( pBlock->right < x ){
              distX = x - pBlock->right;
              TestPoint(0);
            }else{
              distX = 0;
              TestPoint(0);
            }
            if( distX + 4*distY < dist ){
              dist = distX + 4*distY;
              pNearby = pBlock;
              TestPoint(0);
            }else{
              TestPoint(0);
            }
          }
        }
      }
      if( pBlock==0 ){
        if( pNearby ){
          HtmlLock(htmlPtr);
          FindIndexInBlock(htmlPtr, pNearby, x, ppToken, pIndex);
          if( HtmlUnlock(htmlPtr) ) return 1;
          TestPoint(0);
        }else{
          TestPoint(0);
        }
      }else{
        TestPoint(0);
      }
      break;
    default:
      rc = 1;
      TestPoint(0);
      break;
  }
  return rc;
}
Esempio n. 11
0
/*
** Given a Block and an x coordinate, find the Index of the character
** that is closest to the given x coordinate.
**
** The x-coordinate might specify a point to the left of the block,
** in which case the procedure returns the first token and a character
** index of 0.  Or the x-coordinate might specify a point to the right
** of the block, in which case the last token is returned with an index
** equal to its last character.
*/
static void FindIndexInBlock(
  HtmlWidget *htmlPtr,       /* The widget */
  HtmlBlock *pBlock,         /* The block */
  int x,                     /* The x coordinate */
  HtmlElement **ppToken,     /* Write the closest token here */
  int *pIndex                /* Write the charater index in ppToken here */
){
  HtmlElement *p;
  Tk_Font font;
  int len;
  int n;

  p = pBlock->base.pNext;
  HtmlLock(htmlPtr);
  font = HtmlGetFont(htmlPtr, p->base.style.font);
  if( HtmlUnlock(htmlPtr) ){
    *ppToken = p;
    *pIndex = 0;
    return;
  }
  if( x <= pBlock->left ){
    *ppToken = p;
    *pIndex = 0;
    TestPoint(0);
    return;
  }else if( x>= pBlock->right ){
    *ppToken = p;
    *pIndex = 0;
    while( p && p->base.type!=Html_Block ){
      *ppToken = p;
      p = p->base.pNext;
      TestPoint(0);
    }
    p = *ppToken;
    if( p && p->base.type==Html_Text ){
      *pIndex = p->base.count - 1;
      TestPoint(0);
    }else{
      TestPoint(0);
    }
    return;
  }
  if( pBlock->n==0 ){
    *ppToken = p;
    *pIndex = 0;
    TestPoint(0);
  }else{
    TestPoint(0);
  }
  n = Tk_MeasureChars(font, pBlock->z, pBlock->n, x - pBlock->left, 0, &len);
  *pIndex = 0;
  *ppToken = 0;
  while( p && n>=0 ){
    switch( p->base.type ){
      case Html_Text:
        if( n<p->base.count ){
          *pIndex = n;
          TestPoint(0);
        }else{
          *pIndex = p->base.count - 1;
          TestPoint(0);
        }
        *ppToken = p;
        n -= p->base.count;
        break;
      case Html_Space:
        if( p->base.style.flags & STY_Preformatted ){
          if( n<p->base.count ){
            *pIndex = n;
            TestPoint(0);
          }else{
            *pIndex = p->base.count - 1;
            TestPoint(0);
          }
          *ppToken = p;
          n -= p->base.count;
        }else{
          *pIndex = 0;
          *ppToken = p;
          n--;
          TestPoint(0);
        }
        break;
      default:
        TestPoint(0);
        break;
    }
    if( p ){
      p = p->base.pNext;
      TestPoint(0);
    }else{
      TestPoint(0);
    }
  }
}
Esempio n. 12
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. 13
0
/*
** Do as much layout as possible on the block of text defined by
** the HtmlLayoutContext.
*/
void HtmlLayoutBlock(HtmlLayoutContext *pLC){
  HtmlElement *p, *pNext;

  for(p=pLC->pStart; p && p!=pLC->pEnd; p=pNext){
    int lineWidth;
    int actualWidth;
    int y = 0;
    int leftMargin;
    int maxX = 0;

    /* Do as much break markup as we can. */
    while( p && p!=pLC->pEnd ){
      HtmlLock(pLC->htmlPtr);
      pNext = DoBreakMarkup(pLC, p);
      if( HtmlUnlock(pLC->htmlPtr) ) return;
      if( pNext==p ){ TestPoint(0); break; }
      if( pNext ){
        TRACE(HtmlTrace_BreakMarkup,
           ("Processed token %s as break markup\n", HtmlTokenName(p)));
        pLC->pStart = p;
      }
      p = pNext;
      TestPoint(0);
    }
    if( p==0 || p==pLC->pEnd ){ TestPoint(0); break; }

#ifdef TABLE_TRIM_BLANK
    HtmlLineWasBlank = 0;
#endif /* TABLE_TRIM_BLANK */

    /* We might try several times to layout a single line... */   
    while( 1 ){

      /* Compute margins */
      HtmlComputeMargins(pLC, &leftMargin, &y, &lineWidth);

      /* Layout a single line of text */
      pNext = GetLine(pLC, p, pLC->pEnd, lineWidth, pLC->left-leftMargin,
                      &actualWidth);
      TRACE(HtmlTrace_GetLine,
         ("GetLine page=%d left=%d right=%d available=%d used=%d\n",
         pLC->pageWidth, pLC->left, pLC->right, lineWidth, actualWidth));
      FixAnchors(p,pNext,pLC->bottom);

      /* Move down and repeat the layout if we exceeded the available
      ** line length and it is possible to increase the line length by
      ** moving past some obsticle.
      */
      if( actualWidth > lineWidth && InWrapAround(pLC) ){
        ClearObstacle(pLC, CLEAR_First);
        TestPoint(0);
        continue;
      }

      /* Lock the line into place and exit the loop */
      y = FixLine(p, pNext, y, lineWidth, actualWidth, leftMargin, &maxX);
      TestPoint(0);
      break;
    }

#ifdef TABLE_TRIM_BLANK
	/*
	 * I noticed that a newline following break markup would result
	 * in a blank line being drawn. So if an "empty" line was found
	 * I subtract any whitespace caused by break markup.
	 */
	if (actualWidth <= 0)
	{
		HtmlLineWasBlank = 1;
	}
#endif /* TABLE_TRIM_BLANK */

    /* If a line was completed, advance to the next line */
    if( pNext && actualWidth>0 && y > pLC->bottom ){
      pLC->bottom = y;
      pLC->headRoom = 0;
      pLC->pStart = pNext;
    }
    if( y > pLC->maxY ){
      pLC->maxY = y;
    }
    if( maxX > pLC->maxX ){
      pLC->maxX = maxX;
    }
  }
}
Esempio n. 14
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;
}