Ejemplo n.º 1
0
/* Draw the selection background for the given block
*/
static void DrawSelectionBackground(
  HtmlWidget *htmlPtr,      /* The HTML widget */
  HtmlBlock *pBlock,        /* The block whose background is drawn */
  Drawable drawable,        /* Draw the background on this drawable */
  int x, int y              /* Virtual coords of top-left of drawable */
){
  int xLeft, xRight;        /* Left and right bounds of box to draw */
  int yTop, yBottom;        /* Top and bottom of box */
  HtmlElement *p = 0;       /* First element of the block */
  Tk_Font font;             /* Font */
  GC gc;                    /* GC for drawing */
  XRectangle xrec;          /* Size of a filled rectangle to be drawn */

  if( pBlock==0 || (pBlock->base.flags & HTML_Selected)==0 ){
    TestPoint(0);
    return;
  }
  xLeft = pBlock->left - x;
  if( pBlock==htmlPtr->pSelStartBlock && htmlPtr->selStartIndex>0 ){
    if( htmlPtr->selStartIndex >= pBlock->n ){ TestPoint(0); return; }
    p = pBlock->base.pNext;
    font = HtmlGetFont(htmlPtr, p->base.style.font);
    if( font==0 ) return;
    if( p->base.type==Html_Text ){
      xLeft = p->text.x - x + Tk_TextWidth(font, pBlock->z, 
                                           htmlPtr->selStartIndex);
    }
  }
  xRight = pBlock->right - x;
  if( pBlock==htmlPtr->pSelEndBlock && htmlPtr->selEndIndex<pBlock->n ){
    if( p==0 ){
      p = pBlock->base.pNext;
      font = HtmlGetFont(htmlPtr, p->base.style.font);
      if( font==0 ) return;
    }
    if( p->base.type==Html_Text ){
      xRight = p->text.x - x + Tk_TextWidth(font, pBlock->z,
                                            htmlPtr->selEndIndex);
    }
  }
  yTop = pBlock->top - y;
  yBottom = pBlock->bottom - y;
  gc = HtmlGetGC(htmlPtr, COLOR_Selection, FONT_Any);
  xrec.x = xLeft;
  xrec.y = yTop;
  xrec.width = xRight - xLeft;
  xrec.height = yBottom - yTop;
  XFillRectangles(htmlPtr->display, drawable, gc, &xrec, 1);
}
Ejemplo n.º 2
0
/*
** Increase the headroom to create a paragraph break at the current token
*/
static void Paragraph(
  HtmlLayoutContext *pLC,
  HtmlElement *p
){
  int headroom;

  if( p==0 ){ TestPoint(0); return; }
  if( p->base.type==Html_Text ){
    headroom = p->text.ascent + p->text.descent;
    TestPoint(0);
  }else if( p->pNext && p->pNext->base.type==Html_Text ){
    headroom = p->pNext->text.ascent + p->pNext->text.descent;
    TestPoint(0);
  }else{
    Tk_FontMetrics fontMetrics;
    Tk_Font font;
    font = HtmlGetFont(pLC->htmlPtr, p->base.style.font);
    if( font==0 ) return;   
    Tk_GetFontMetrics(font, &fontMetrics);
    headroom = fontMetrics.descent + fontMetrics.ascent;
    TestPoint(0);
  }
  if( pLC->headRoom < headroom && pLC->bottom > pLC->top ){
    pLC->headRoom = headroom;
  }
}
Ejemplo n.º 3
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;
  }
}
Ejemplo n.º 4
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;
    }
  }
}
Ejemplo n.º 5
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);
    }
  }
}