示例#1
0
void HtmlPrintList(HtmlElement *p, HtmlElement *pEnd){
  while( p && p!=pEnd ){
    if( p->base.type==Html_Block ){
      char *z = p->block.z;
      int n = p->block.n;
      if( n==0 || z==0 ){
        n = 1;
        z = "";
      }
      printf("Block 0x%08x flags=%02x cnt=%d x=%d..%d y=%d..%d z=\"%.*s\"\n",
        (int)p, p->base.flags, p->base.count, p->block.left, p->block.right,
        p->block.top, p->block.bottom, n, z);
    }else{
      printf("Token 0x%08x font=%2d color=%2d align=%d flags=0x%04x name=%s\n",
        (int)p, p->base.style.font, p->base.style.color,
        p->base.style.align, p->base.style.flags, HtmlTokenName(p));
    }
    p = p->pNext;
  }
}
示例#2
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;
}
示例#3
0
/*
** This routine gathers as many tokens as will fit on one line.
**
** The candidate tokens begin with pStart and go thru the end of
** the list or to pEnd, whichever comes first.  The first token
** at the start of the next line is returned.  NULL is returned if
** we exhaust data.
**
** "width" is the maximum allowed width of the line.  The actual
** width is returned in *actualWidth.  The actual width does not
** include any trailing spaces.  Sometimes the actual width will
** be greater than the maximum width.  This will happen, for example,
** for text enclosed in <pre>..</pre> that has lines longer than
** the width of the page.
**
** If the list begins with text, at least one token is returned,
** even if that one token is longer than the allowed line length.
** But if the list begins with some kind of break markup (possibly
** preceded by white space) then the returned list may be empty.
**
** The "x" coordinates of all elements are set assuming that the line
** begins at 0.  The calling routine should adjust these coordinates
** to position the line horizontally.  (The FixLine() procedure does
** this.)  Note that the "x" coordinate of <li> elements will be negative.
** Text within <dt>..</dt> might also have a negative "x" coordinate.
** But in no case will the x coordinate every be less than "minX".
*/
static HtmlElement *GetLine(
  HtmlLayoutContext *pLC,      /* The complete layout context.  */
  HtmlElement *pStart,         /* First token on new line */
  HtmlElement *pEnd,           /* End of line.  Might be NULL */
  int width,                   /* How much space is on this line */
  int minX,                    /* The minimum value of the X coordinate */
  int *actualWidth             /* Return space actually required */
){
  int x;                       /* Current X coordinate */
  int spaceWanted = 0;         /* Add this much space before next token */
  HtmlElement *p;              /* For looping over tokens */
  HtmlElement *lastBreak = 0;  /* Last line-break opportunity */
  int isEmpty = 1;             /* True if link contains nothing */
  int origin;                  /* Initial value of "x" */
  
  *actualWidth = 0;
  p = pStart;
  while( p && p!=pEnd && (p->base.style.flags & STY_Invisible)!=0 ){
    p = p->pNext;
  }
  if( p && p->base.style.flags & STY_DT ){
    origin = -HTML_INDENT;
  }else{
    origin = 0;
  }
  x = origin;
  if( x<minX ){ x = minX; }
  if( p && p!=pEnd && p->base.type==Html_LI ){
    p->li.x = x - HTML_INDENT/3;
    if( p->li.x - (HTML_INDENT*2)/3<minX ){
      x += minX - p->li.x + (HTML_INDENT*2)/3;
      p->li.x = minX + (HTML_INDENT*2)/3;
    }
    isEmpty = 0;
    *actualWidth = 1;
    p = p->pNext;
    while( p && (p->base.type==Html_Space || p->base.type==Html_P) ){
      p = p->pNext;
    }
  }
  for(; p && p!=pEnd; p=p->pNext){
    if( p->base.style.flags & STY_Invisible ){
      continue;
    }
    switch( p->base.type ){
      case Html_Text:
        p->text.x = x + spaceWanted;
        if( (p->base.style.flags & STY_Preformatted) == 0 ){
          if( lastBreak && x + spaceWanted + p->text.w > width ){
            TestPoint(0);
            return lastBreak;
          }
        }
        TRACE(HtmlTrace_GetLine2, ("Place token %s at x=%d w=%d\n",
           HtmlTokenName(p), p->text.x, p->text.w));
        x += p->text.w + spaceWanted;
        isEmpty = 0;
        spaceWanted = 0;
        break;

      case Html_Space:
        if( p->base.style.flags & STY_Preformatted ){
          if( p->base.flags & HTML_NewLine ){
            *actualWidth = x<=0 ? 1 : x;
            TestPoint(0);
            return p->pNext;
          }
          x += p->space.w * p->base.count;
          TestPoint(0);
        }else{
          int w;
          if( (p->base.style.flags & STY_NoBreak)==0 ){
            lastBreak = p->pNext;
            *actualWidth = x<=0 && !isEmpty ? 1 : x;
          }
          w = p->space.w;
          if( spaceWanted < w && x>origin ){
            spaceWanted = w;
          }
        }
        break;

      case Html_IMG:
        switch( p->image.align ){
          case IMAGE_ALIGN_Left:
          case IMAGE_ALIGN_Right:
            *actualWidth = x<=0 && !isEmpty ? 1 : x;
            return p;
          default:
            break;
        }
        p->image.x = x + spaceWanted;
        if( (p->base.style.flags & STY_Preformatted) == 0 ){
          if( lastBreak && x + spaceWanted + p->image.w > width ){
            TestPoint(0);
            return lastBreak;
          }
        }
        TRACE(HtmlTrace_GetLine2, ("Place in-line image %s at x=%d w=%d\n",
           HtmlTokenName(p), p->image.x, p->image.w));
        x += p->image.w + spaceWanted;
        if( (p->base.style.flags & STY_NoBreak)==0 ){
          lastBreak = p->pNext;
          *actualWidth = x<=0 && !isEmpty ? 1 : x;
        }
        spaceWanted = 0;
        isEmpty = 0;
        break;

      case Html_APPLET:
      case Html_EMBED:
      case Html_INPUT:
      case Html_SELECT:
      case Html_TEXTAREA:
        p->input.x = x + spaceWanted + p->input.padLeft;
        if( (p->base.style.flags & STY_Preformatted) == 0 ){
          if( lastBreak && x + spaceWanted + p->input.w > width ){
            TestPoint(0);
            return lastBreak;
          }
        }
        TRACE(HtmlTrace_GetLine2, ("Place token %s at x=%d w=%d\n",
           HtmlTokenName(p), p->input.x, p->input.w));
        x = p->input.x + p->input.w;
        if( (p->base.style.flags & STY_NoBreak)==0 ){
          lastBreak = p->pNext;
          *actualWidth = x<=0 && !isEmpty ? 1 : x;
        }
        spaceWanted = 0;
        isEmpty = 0;
        break;

      case Html_EndTEXTAREA:
        if( p->ref.pOther ){
          /* HtmlResetTextarea(pLC->htmlPtr, p->ref.pOther); */
        }
        break;

      case Html_DD:
        if( p->ref.pOther==0 ) break;
        if( p->ref.pOther->list.compact==0 || x + spaceWanted >= 0 ){
          *actualWidth = x<=0 && !isEmpty ? 1 : x;
          return p;
        }
        x = 0;
        spaceWanted = 0;
        break;

      case Html_WBR:
        *actualWidth = x<=0 && !isEmpty ? 1 : x;
        if( x + spaceWanted >= width ){
          return p->pNext;
        }else{
          lastBreak = p->pNext;
        }
        break;

      case Html_ADDRESS:
      case Html_EndADDRESS:
      case Html_BLOCKQUOTE:
      case Html_EndBLOCKQUOTE:
      case Html_BODY:
      case Html_EndBODY:
      case Html_BR:
      case Html_CAPTION:
      case Html_EndCAPTION:
      case Html_CENTER:
      case Html_EndCENTER:
      case Html_EndDD:
      case Html_DIV:
      case Html_EndDIV:
      case Html_DL:
      case Html_EndDL:
      case Html_DT:
      case Html_H1:
      case Html_EndH1:
      case Html_H2:
      case Html_EndH2:
      case Html_H3:
      case Html_EndH3:
      case Html_H4:
      case Html_EndH4:
      case Html_H5:
      case Html_EndH5:
      case Html_H6:
      case Html_EndH6:
      case Html_EndHTML:
      case Html_HR:
      case Html_LI:
      case Html_LISTING:
      case Html_EndLISTING:
      case Html_MENU:
      case Html_EndMENU:
      case Html_OL:
      case Html_EndOL:
      case Html_P:
      case Html_EndP:
      case Html_PRE:
      case Html_EndPRE:
      case Html_TABLE:
      case Html_EndTABLE:
      case Html_TD:
      case Html_EndTD:
      case Html_TH:
      case Html_EndTH:
      case Html_TR:
      case Html_EndTR:
      case Html_UL:
      case Html_EndUL:
        *actualWidth = x<=0 && !isEmpty ? 1 : x;
        return p;

      default:
        break;
    }
  }
  *actualWidth = x<=0 && !isEmpty ? 1 : x;
  return p;
}
示例#4
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;
    }
  }
}