46 TGHtmlBlock::TGHtmlBlock() : TGHtmlElement(Html_Block)
59 TGHtmlBlock::~TGHtmlBlock()
69 void TGHtml::UnlinkAndFreeBlock(TGHtmlBlock *pBlock)
72 pBlock->fPNext->fPPrev = pBlock->fPPrev;
74 fPLast = pBlock->fPPrev;
77 pBlock->fPPrev->fPNext = pBlock->fPNext;
79 fPFirst = pBlock->fPNext;
81 pBlock->fPPrev = pBlock->fPNext = 0;
92 void TGHtml::AppendBlock(TGHtmlElement *pToken, TGHtmlBlock *pBlock)
94 pBlock->fPPrev = pToken->fPPrev;
95 pBlock->fPNext = pToken;
96 pBlock->fBPrev = fLastBlock;
99 fLastBlock->fBNext = pBlock;
101 fFirstBlock = pBlock;
104 if (pToken->fPPrev) {
105 pToken->fPPrev->fPNext = (TGHtmlElement *) pBlock;
107 fPFirst = (TGHtmlElement *) pBlock;
109 pToken->fPPrev = (TGHtmlElement *) pBlock;
120 static void GetLetterIndex(
char *zBuf,
int index,
int isUpper)
124 if (index < 1 || index > 52) {
126 sprintf(zBuf,
"%d", index);
139 zBuf[0] = seed + index;
143 zBuf[0] = seed + index;
144 zBuf[1] = seed + index;
156 static void GetRomanIndex(
char *zBuf,
int index,
int isUpper)
186 if (index < 1 || index >= 5000) {
188 sprintf(zBuf,
"%d", index);
191 for (j = 0; index > 0 && j <
sizeof(values)/
sizeof(values[0]); j++) {
193 while (index >= values[j].value) {
194 for (k = 0; values[j].name[k]; k++) {
195 zBuf[i++] = values[j].name[k];
197 index -= values[j].value;
202 for (i = 0; zBuf[i]; i++) {
203 zBuf[i] +=
'A' -
'a';
215 void TGHtml::DrawSelectionBackground(TGHtmlBlock *pBlock, Drawable_t drawable,
220 TGHtmlElement *p = 0;
224 if (pBlock == 0 || (pBlock->fFlags & HTML_Selected) == 0)
return;
226 xLeft = pBlock->fLeft - x;
227 if (pBlock == fPSelStartBlock && fSelStartIndex > 0) {
228 if (fSelStartIndex >= pBlock->fN)
return;
230 font = GetFont(p->fStyle.fFont);
231 if (font == 0)
return;
232 if (p->fType == Html_Text) {
233 TGHtmlTextElement *tp = (TGHtmlTextElement *) p;
234 xLeft = tp->fX - x + font->TextWidth(pBlock->fZ, fSelStartIndex);
237 xRight = pBlock->fRight - x;
238 if (pBlock == fPSelEndBlock && fSelEndIndex < pBlock->fN) {
241 font = GetFont(p->fStyle.fFont);
242 if (font == 0)
return;
244 if (p->fType == Html_Text) {
245 TGHtmlTextElement *tp = (TGHtmlTextElement *) p;
246 xRight = tp->fX - x + font->TextWidth(pBlock->fZ, fSelEndIndex);
249 yTop = pBlock->fTop - y;
250 yBottom = pBlock->fBottom - y;
251 gc = GetGC(COLOR_Selection, FONT_Any);
254 UInt_t width = xRight - xLeft;
255 UInt_t height = yBottom - yTop;
256 gVirtualX->FillRectangle(drawable, gc, xx, yy, width, height);
265 void TGHtml::DrawRect(Drawable_t drawable, TGHtmlElement *src,
266 int x,
int y,
int w,
int h,
int depth,
int relief)
269 UInt_t width, height;
273 GContext_t gcLight, gcDark;
275 if (relief != HTML_RELIEF_FLAT) {
277 iLight1 = GetLightShadowColor(src->fStyle.fBgcolor);
278 gcLight = GetGC(iLight1, FONT_Any);
279 iDark1 = GetDarkShadowColor(src->fStyle.fBgcolor);
280 gcDark = GetGC(iDark1, FONT_Any);
281 if (relief == HTML_RELIEF_SUNKEN) {
282 GContext_t gcTemp = gcLight;
287 gcLight = GetGC(src->fStyle.fColor, FONT_Any);
294 gVirtualX->FillRectangle(drawable, gcLight, xx, yy, width, height);
296 gVirtualX->FillRectangle(drawable, gcLight, xx, yy, width, height);
297 for (i = 0; i < depth && i < h/2; i++) {
298 gVirtualX->DrawLine(drawable, gcLight, x+i, y+i, x+w-i-1, y+i);
299 gVirtualX->DrawLine(drawable, gcDark, x+i, y+h-i-1, x+w-i-1, y+h-i-1);
302 if (h > depth*2 && w > depth*2) {
304 gcBg = GetGC(src->fStyle.fBgcolor, FONT_Any);
308 height = h - depth*2;
309 gVirtualX->FillRectangle(drawable, gcBg, xx, yy, width, height);
316 void TGHtml::BlockDraw(TGHtmlBlock *pBlock, Drawable_t drawable,
317 int drawableLeft,
int drawableTop,
318 int drawableWidth,
int drawableHeight,
326 UInt_t width, height;
328 if (pBlock == 0)
return;
330 src = pBlock->fPNext;
331 while (src && (src->fFlags & HTML_Visible) == 0) src = src->fPNext;
333 if (src == 0)
return;
335 if (pBlock->fN > 0) {
337 if (src->fType == Html_Text) {
338 TGHtmlTextElement *tsrc = (TGHtmlTextElement *) src;
345 if (pBlock->fFlags & HTML_Selected) {
346 DrawSelectionBackground(pBlock, drawable, drawableLeft, drawableTop);
348 gc = GetGC(src->fStyle.fColor, src->fStyle.fFont);
349 font = GetFont(src->fStyle.fFont);
350 if (font == 0)
return;
351 font->DrawChars(drawable, gc, pBlock->fZ, pBlock->fN,
352 x - drawableLeft, y - drawableTop);
353 if (src->fStyle.fFlags & STY_Underline) {
354 font->UnderlineChars(drawable, gc, pBlock->fZ,
355 x - drawableLeft, y-drawableTop, 0, pBlock->fN);
357 if (src->fStyle.fFlags & STY_StrikeThru) {
358 x = pBlock->fLeft - drawableLeft;
359 y = (pBlock->fTop + pBlock->fBottom) / 2 - drawableTop;
360 width = pBlock->fRight - pBlock->fLeft;
361 height = 1 + (pBlock->fBottom - pBlock->fTop > 15);
362 gVirtualX->FillRectangle(drawable, gc, x, y, width, height);
364 if (pBlock == fPInsBlock && fInsStatus > 0) {
365 if (fInsIndex < pBlock->fN) {
366 TGHtmlTextElement *tsrc = (TGHtmlTextElement *) src;
367 x = tsrc->fX - drawableLeft;
368 x += font->TextWidth(pBlock->fZ, fInsIndex);
370 x = pBlock->fRight - drawableLeft;
373 gVirtualX->FillRectangle(drawable, gc, x, pBlock->fTop - drawableTop,
374 2, pBlock->fBottom - pBlock->fTop);
382 TGHtmlImageMarkup *image;
383 switch (src->fType) {
385 li = (TGHtmlLi *) src;
388 switch (li->fLtype) {
391 sprintf(zBuf,
"%d.", li->fCnt);
394 GetLetterIndex(zBuf, li->fCnt, 1);
397 GetLetterIndex(zBuf, li->fCnt, 0);
400 GetRomanIndex(zBuf, li->fCnt, 1);
403 GetRomanIndex(zBuf, li->fCnt, 0);
409 gc = GetGC(src->fStyle.fColor, src->fStyle.fFont);
410 switch (li->fLtype) {
411 case LI_TYPE_Undefined:
412 case LI_TYPE_Bullet1:
418 case LI_TYPE_Bullet2:
424 case LI_TYPE_Bullet3:
425 gVirtualX->DrawRectangle(drawable, gc, x - 7 - drawableLeft,
426 y - 8 - drawableTop, 7, 7);
435 font = GetFont(src->fStyle.fFont);
436 if (font == 0)
return;
437 w = font->TextWidth(zBuf, cnt);
438 font->DrawChars(drawable, gc, zBuf, cnt,
439 x - w - drawableLeft, y - drawableTop);
445 TGHtmlHr *hr = (TGHtmlHr *) src;
446 int relief = fRuleRelief;
448 case HTML_RELIEF_RAISED:
449 case HTML_RELIEF_SUNKEN:
452 relief = HTML_RELIEF_FLAT;
455 DrawRect(drawable, src, hr->fX - drawableLeft, hr->fY - drawableTop,
456 hr->fW, hr->fH, 1, relief);
461 TGHtmlTable *table = (TGHtmlTable *) src;
462 int relief = fTableRelief;
463 if ((!fBgImage || src->fStyle.fExpbg) && !table->fHasbg) {
465 case HTML_RELIEF_RAISED:
466 case HTML_RELIEF_SUNKEN:
469 relief = HTML_RELIEF_FLAT;
473 DrawRect(drawable, src, table->fX - drawableLeft,
474 table->fY - drawableTop, table->fW, table->fH,
475 table->fBorderWidth, relief);
478 if (table->fBgImage) {
479 DrawTableBgnd(table->fX, table->fY, table->fW, table->fH, pixmap,
487 TGHtmlCell *cell = (TGHtmlCell *) src;
490 pTable = cell->fPTable;
491 if ((!fBgImage || src->fStyle.fExpbg) && !(pTable && pTable->fHasbg)) {
492 depth = pTable && (pTable->fBorderWidth > 0);
493 switch (fTableRelief) {
494 case HTML_RELIEF_RAISED: relief = HTML_RELIEF_SUNKEN;
break;
495 case HTML_RELIEF_SUNKEN: relief = HTML_RELIEF_RAISED;
break;
496 default: relief = HTML_RELIEF_FLAT;
break;
498 DrawRect(drawable, src,
499 cell->fX - drawableLeft, cell->fY - drawableTop,
500 cell->fW, cell->fH, depth, relief);
503 if (cell->fBgImage) {
504 DrawTableBgnd(cell->fX, cell->fY, cell->fW, cell->fH, pixmap,
506 }
else if (cell->fPRow && (bgImg = ((TGHtmlRef *)cell->fPRow)->fBgImage)) {
507 DrawTableBgnd(cell->fX, cell->fY, cell->fW, cell->fH, pixmap, bgImg);
513 image = (TGHtmlImageMarkup *) src;
514 if (image->fPImage) {
515 DrawImage(image, drawable, drawableLeft, drawableTop,
516 drawableLeft + drawableWidth,
517 drawableTop + drawableHeight);
518 }
else if (image->fZAlt) {
519 gc = GetGC(src->fStyle.fColor, src->fStyle.fFont);
520 font = GetFont(src->fStyle.fFont);
521 if (font == 0)
return;
522 font->DrawChars(drawable, gc,
523 image->fZAlt, strlen(image->fZAlt),
524 image->fX - drawableLeft,
525 image->fY - drawableTop);
538 void TGHtml::DrawImage(TGHtmlImageMarkup *image, Drawable_t drawable,
539 int drawableLeft,
int drawableTop,
540 int drawableRight,
int drawableBottom)
547 imageTop = image->fY - image->fAscent;
548 y = imageTop - drawableTop;
549 if (imageTop + image->fH > drawableBottom) {
550 imageH = drawableBottom - imageTop;
561 x = image->fX - drawableLeft;
562 if (image->fX + image->fW > drawableRight) {
563 imageW = drawableRight - image->fX;
575 TImage *img = image->fPImage->fImage;
577 imageH = imageH < 0 ? -imageH : imageH;
578 imageW = imageW < 0 ? -imageW : imageW;
580 img->PaintImage(drawable, x, y, imageX, imageY, imageW, imageH);
583 image->fRedrawNeeded = 0;
590 void TGHtml::AnimateImage(TGHtmlImage * )
616 TGHtmlElement *TGHtml::FillOutBlock(TGHtmlBlock *p)
619 TGHtmlElement *pElem;
626 if (p->fN) p->fN = 0;
628 if (p->fZ)
delete[] p->fZ;
635 while (pElem && (pElem->fFlags & HTML_Visible) == 0) {
636 TGHtmlElement *fPNext = pElem->fPNext;
637 if (pElem->fType == Html_Block) {
638 UnlinkAndFreeBlock((TGHtmlBlock *) pElem);
644 if (pElem == 0)
return 0;
648 if (pElem->fType != Html_Text) {
649 switch (pElem->fType) {
651 TGHtmlHr *hr = (TGHtmlHr *) pElem;
652 p->fTop = hr->fY - hr->fH;
655 p->fRight = hr->fX + hr->fW;
660 TGHtmlLi *li = (TGHtmlLi *) pElem;
661 p->fTop = li->fY - li->fAscent;
662 p->fBottom = li->fY + li->fDescent;
663 p->fLeft = li->fX - 10;
664 p->fRight = li->fX + 10;
670 TGHtmlCell *cell = (TGHtmlCell *) pElem;
672 p->fBottom = cell->fY + cell->fH;
674 p->fRight = cell->fX + cell->fW;
679 TGHtmlTable *table = (TGHtmlTable *) pElem;
681 p->fBottom = table->fY + table->fH;
682 p->fLeft = table->fX;
683 p->fRight = table->fX + table->fW;
688 TGHtmlImageMarkup *image = (TGHtmlImageMarkup *) pElem;
689 p->fTop = image->fY - image->fAscent;
690 p->fBottom = image->fY + image->fDescent;
691 p->fLeft = image->fX;
692 p->fRight = image->fX + image->fW;
698 return pElem->fPNext;
703 TGHtmlTextElement *text = (TGHtmlTextElement *) pElem;
707 p->fTop = y - text->fAscent;
708 p->fBottom = y + text->fDescent;
710 style = pElem->fStyle;
713 TGHtmlElement *fPNext = pElem->fPNext;
714 switch (pElem->fType) {
716 TGHtmlTextElement *txt = (TGHtmlTextElement *) pElem;
717 if (pElem->fFlags & STY_Invisible) {
720 if (txt->fSpaceWidth <= 0) {
725 || style.fFont != pElem->fStyle.fFont
726 || style.fColor != pElem->fStyle.fColor
727 || (style.fFlags & STY_FontMask)
728 != (pElem->fStyle.fFlags & STY_FontMask)) {
731 int sw = txt->fSpaceWidth;
732 int nSpace = (txt->fX - x) / sw;
733 if (nSpace * sw + x != txt->fX) {
735 }
else if ((n + nSpace + pElem->fCount) >= (int)
sizeof(zBuf)) {
737 for (i = 0; i < nSpace && (n+1) < (
int)sizeof(zBuf); ++i) {
740 strncpy(&zBuf[n], txt->fZText,
sizeof(zBuf) - n - 1);
741 zBuf[
sizeof(zBuf)-1] = 0;
743 x = txt->fX + txt->fW;
745 for (i = 0; i < nSpace && (n+1) < (
int)sizeof(zBuf); ++i) {
748 strncpy(&zBuf[n], txt->fZText,
sizeof(zBuf) - n - 1);
749 zBuf[
sizeof(zBuf)-1] = 0;
751 x = txt->fX + txt->fW;
758 if (pElem->fStyle.fFont != style.fFont) {
759 pElem = pElem->fPNext;
761 }
else if ((style.fFlags & STY_Preformatted) != 0 &&
762 (pElem->fFlags & HTML_NewLine) != 0) {
763 pElem = pElem->fPNext;
769 UnlinkAndFreeBlock((TGHtmlBlock *) pElem);
778 if (pElem->fFlags & HTML_Visible) go = 0;
787 while (n > 0 && zBuf[n-1] ==
' ') n--;
788 p->fZ =
new char[n+1];
789 strlcpy(p->fZ, zBuf, n+1);
805 TGHtmlElement *TGHtml::FindStartOfNextBlock(TGHtmlElement *p,
int *pCnt)
809 while (p && (p->fFlags & HTML_Visible) == 0) {
810 TGHtmlElement *fPNext = p->fPNext;
811 if (p->fType == Html_Block) {
812 UnlinkAndFreeBlock((TGHtmlBlock *) p);
818 if (pCnt) *pCnt = cnt;
830 void TGHtml::FormBlocks()
832 TGHtmlElement *pElem;
835 pElem = FillOutBlock(fLastBlock);
841 pElem = FindStartOfNextBlock(pElem, &cnt);
843 TGHtmlBlock *pNew =
new TGHtmlBlock();
845 fLastBlock->fCount += cnt;
847 AppendBlock(pElem, pNew);
848 pElem = FillOutBlock(pNew);
856 void TGHtml::DrawTableBgnd(
int l,
int t,
int w,
int h,
857 Drawable_t pixmap, TImage *image)
860 int dl, dt, dr, db, left, top, right, bottom;
862 left = l - fVisible.fX;
863 top = t - fVisible.fY;
870 right = left + w - 1;
871 bottom = top + h - 1;
872 if (dr == 0 && db == 0) { dr = right; db = bottom; }
873 if (left > dr || right < dl || top > db || bottom < dt)
return;
876 int iw = image->GetWidth();
877 int ih = image->GetHeight();
878 if (iw < 4 && ih < 4)
return;
879 sx = (left + _visibleStart.x) % iw;
881 for (mx = left - dl; w > 0; mx += sw, sw = iw, sx = 0) {
883 sy = (top + _visibleStart.y) % ih;
885 for (my = top - dt, hd = h; hd > 0; my += sh, sh = ih, sy = 0) {
886 if (sh > hd) sh = hd;
888 image->Draw(pixmap, GetAnyGC(), sx, sy, sw, sh, mx, my);
894 if (!image->GetPixmap())
return;
895 GContext_t gc = GetAnyGC();
899 gcv.fTile = image->GetPixmap();
900 gcv.fFillStyle = kFillTiled;
901 gcv.fTsXOrigin = -fVisible.fX - fDirtyLeft;
902 gcv.fTsYOrigin = -fVisible.fY - fDirtyTop;
903 gVirtualX->ChangeGC(gc, &gcv);
905 gVirtualX->FillRectangle(pixmap, gc, left - dl, top - dt, w, h);
908 gcv.fFillStyle = kFillSolid;
909 gVirtualX->ChangeGC(gc, &gcv);