00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <ctype.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037
00038 #include "TSystem.h"
00039 #include "TGHtml.h"
00040 #include "THashTable.h"
00041 #include "TObjString.h"
00042 #include "TGIdleHandler.h"
00043 #include "TImage.h"
00044 #include "TGScrollBar.h"
00045 #include "TGTextEntry.h"
00046 #include "TGText.h"
00047 #include "Riostream.h"
00048 #include "TGComboBox.h"
00049 #include "TGListBox.h"
00050
00051
00052
00053
00054
00055
00056
00057
00058 ClassImp(TGHtml)
00059
00060 int HtmlTraceMask = 0;
00061 int HtmlDepth = 0;
00062
00063 #define DEF_FRAME_BG_COLOR "#c0c0c0"
00064 #define DEF_FRAME_CURSOR ""
00065 #define DEF_BUTTON_FG "black"
00066 #define DEF_BUTTON_HIGHLIGHT_BG "#d9d9d9"
00067 #define DEF_BUTTON_HIGHLIGHT "black"
00068
00069
00070
00071 TGHtml::TGHtml(const TGWindow *p, int w, int h, int id) : TGView(p, w, h, id)
00072 {
00073
00074
00075 int i;
00076
00077 fExiting = 0;
00078 fPFirst = 0;
00079 fPLast = 0;
00080 fNToken = 0;
00081 fLastSized = 0;
00082 fNextPlaced = 0;
00083 fFirstBlock = 0;
00084 fLastBlock = 0;
00085 fFirstInput = 0;
00086 fLastInput = 0;
00087 fNInput = 0;
00088 fNForm = 0;
00089 fVarId = 0;
00090 fInputIdx = 0;
00091 fRadioIdx = 0;
00092 fSelBegin.fI = 0;
00093 fSelBegin.fP = 0;
00094 fSelEnd.fI = 0;
00095 fSelEnd.fP = 0;
00096 fPSelStartBlock = 0;
00097 fPSelEndBlock = 0;
00098 fInsOnTime = DEF_HTML_INSERT_ON_TIME;
00099 fInsOffTime = DEF_HTML_INSERT_OFF_TIME;
00100 fInsStatus = 0;
00101 fInsTimer = 0;
00102 fIns.fI = 0;
00103 fIns.fP = 0;
00104 fPInsBlock = 0;
00105 fInsIndex = 0;
00106 fZText = 0;
00107 fNText = 0;
00108 fNAlloc = 0;
00109 fNComplete = 0;
00110 fICol = 0;
00111 fIPlaintext = 0;
00112 fPScript = 0;
00113 fIdle = 0;
00114 fStyleStack = 0;
00115 fParaAlignment = ALIGN_None;
00116 fRowAlignment = ALIGN_None;
00117 fAnchorFlags = 0;
00118 fInDt = 0;
00119 fInTr = 0;
00120 fInTd = 0;
00121 fAnchorStart = 0;
00122 fFormStart = 0;
00123 fFormElemStart = 0;
00124 fFormElemLast = 0;
00125 fLoEndPtr = 0;
00126 fLoFormStart = 0;
00127 fInnerList = 0;
00128 ResetLayoutContext();
00129 fHighlightWidth = 0;
00130 fHighlightBgColorPtr = 0;
00131 fHighlightColorPtr = 0;
00132 for (i = 0; i < N_FONT; ++i) fAFont[i] = 0;
00133 memset(fFontValid, 0, sizeof(fFontValid));
00134 for (i = 0; i < N_COLOR; ++i) {
00135 fApColor[i] = 0;
00136 fIDark[i] = 0;
00137 fILight[i] = 0;
00138 }
00139 fFgColor = AllocColor("black");
00140 fBgColor = AllocColor("white");
00141 fNewLinkColor = AllocColor(DEF_HTML_UNVISITED);
00142 fOldLinkColor = AllocColor(DEF_HTML_VISITED);
00143 fSelectionColor = AllocColor(DEF_HTML_SELECTION_COLOR);
00144
00145 fApColor[COLOR_Normal] = fFgColor;
00146 fApColor[COLOR_Visited] = fOldLinkColor;
00147 fApColor[COLOR_Unvisited] = fNewLinkColor;
00148 fApColor[COLOR_Selection] = fSelectionColor;
00149 fApColor[COLOR_Background] = fBgColor;
00150
00151 fBgImage = 0;
00152
00153 SetBackgroundColor(fApColor[COLOR_Background]->fPixel);
00154 SetBackgroundPixmap(0);
00155
00156 fColorUsed = 0;
00157
00158 for (i = 0; i < N_CACHE_GC; ++i) {
00159 fAGcCache[i].fIndex = 0;
00160 fAGcCache[i].fColor = 0;
00161 fAGcCache[i].fFont = 0;
00162 fAGcCache[i].fGc = 0;
00163 }
00164 fLastGC = 0;
00165 fSelEndIndex =0;
00166 fSelStartIndex = 0;
00167 fGcNextToFree = 0;
00168 fImageList = 0;
00169 fZBaseHref = 0;
00170 fInnerList = 0;
00171 fFormPadding = 5;
00172 fOverrideFonts = 0;
00173 fOverrideColors = 0;
00174 fHasScript = 0;
00175 fHasFrames = 0;
00176 fAddEndTags = 0;
00177 fTableBorderMin = 0;
00178 fVarind = 0;
00179 fIdind = 0;
00180 fInParse = 0;
00181 fZGoto = 0;
00182 fExts = 0;
00183 fUnderlineLinks = kTRUE;
00184 fExportSelection = DEF_HTML_EXPORT_SEL;
00185 fTableRelief = HTML_RELIEF_RAISED;
00186 fRuleRelief = HTML_RELIEF_SUNKEN;
00187 fRulePadding = 5;
00188 fZBase = 0;
00189 fZBaseHref = 0;
00190 fCursor = kPointer;
00191 fMaxX = 0;
00192 fMaxY = 0;
00193
00194 fXMargin = fYMargin = 0;
00195
00196 fFlags = RESIZE_ELEMENTS | RELAYOUT;
00197
00198 fDirtyLeft = LARGE_NUMBER;
00199 fDirtyRight = 0;
00200 fDirtyTop = LARGE_NUMBER;
00201 fDirtyBottom = 0;
00202
00203
00204 fVsb->SetAccelerated();
00205 fHsb->SetAccelerated();
00206
00207 fLastUri = 0;
00208
00209 AddInput(kExposureMask | kFocusChangeMask);
00210 AddInput(kButtonPressMask | kButtonReleaseMask | kPointerMotionMask);
00211
00212 fUidTable = new THashTable(100);
00213 }
00214
00215
00216 TGHtml::~TGHtml()
00217 {
00218
00219
00220 int i;
00221
00222 fExiting = 1;
00223 HClear();
00224 for (i = 0; i < N_FONT; i++) {
00225 if (fAFont[i] != 0) fClient->FreeFont(fAFont[i]);
00226 }
00227 if (fInsTimer) delete fInsTimer;
00228 if (fIdle) delete fIdle;
00229
00230
00231 }
00232
00233
00234 void TGHtml::UpdateBackgroundStart()
00235 {
00236
00237
00238
00239
00240
00241
00242
00243
00244 }
00245
00246
00247 void TGHtml::FreeColor(ColorStruct_t *color)
00248 {
00249
00250
00251 gVirtualX->FreeColor(gClient->GetDefaultColormap(), color->fPixel);
00252 delete color;
00253 }
00254
00255
00256 ColorStruct_t *TGHtml::AllocColor(const char *name)
00257 {
00258
00259
00260 ColorStruct_t *color = new ColorStruct_t;
00261
00262 color->fPixel = 0;
00263 if (gVirtualX->ParseColor(fClient->GetDefaultColormap(), name, *color)) {
00264 if (!gVirtualX->AllocColor(fClient->GetDefaultColormap(), *color)) {
00265
00266 gVirtualX->QueryColor(fClient->GetDefaultColormap(), *color);
00267 gVirtualX->AllocColor(fClient->GetDefaultColormap(), *color);
00268 }
00269 }
00270
00271 return color;
00272 }
00273
00274
00275 ColorStruct_t *TGHtml::AllocColorByValue(ColorStruct_t *color)
00276 {
00277
00278
00279 ColorStruct_t *c = new ColorStruct_t;
00280 *c = *color;
00281
00282 if (!gVirtualX->AllocColor(gClient->GetDefaultColormap(), *c)) {
00283
00284 c->fPixel = 0;
00285 gVirtualX->QueryColor(gClient->GetDefaultColormap(), *c);
00286 gVirtualX->AllocColor(gClient->GetDefaultColormap(), *c);
00287 }
00288
00289 return c;
00290 }
00291
00292
00293 void TGHtml::Clear(Option_t *)
00294 {
00295
00296
00297
00298 HClear();
00299 TGView::Clear();
00300 fFlags |= REDRAW_TEXT | VSCROLL | HSCROLL;
00301 ScheduleRedraw();
00302 }
00303
00304
00305 int TGHtml::ParseText(char *text, const char *index)
00306 {
00307
00308
00309
00310
00311
00312
00313 SHtmlIndex_t iStart;
00314 TGHtmlElement *savePtr=0;
00315
00316 iStart.fP = 0;
00317 iStart.fI = 0;
00318
00319 fLoEndPtr = fPLast;
00320
00321 if (index) {
00322 int rc = GetIndex(index, &iStart.fP, &iStart.fI);
00323 if (rc != 0) return kFALSE;
00324 if (iStart.fP) {
00325 savePtr = iStart.fP->fPNext;
00326 fPLast = iStart.fP;
00327 iStart.fP->fPNext = 0;
00328 }
00329 }
00330
00331 TokenizerAppend(text);
00332
00333 if (fLoEndPtr) {
00334 fFormStart = fLoFormStart;
00335 if (iStart.fP && savePtr) {
00336 AddStyle(fLoEndPtr);
00337 fPLast->fPNext = savePtr;
00338 savePtr->fPPrev = fPLast;
00339 fPLast = fLoEndPtr;
00340 fFlags |= REDRAW_TEXT | RELAYOUT;
00341 ScheduleRedraw();
00342 } else if (fLoEndPtr->fPNext) {
00343 AddStyle(fLoEndPtr->fPNext);
00344 }
00345 } else if (fPFirst) {
00346 fParaAlignment = ALIGN_None;
00347 fRowAlignment = ALIGN_None;
00348 fAnchorFlags = 0;
00349 fInDt = 0;
00350 fAnchorStart = 0;
00351 fFormStart = 0;
00352 fInnerList = 0;
00353 fNInput = 0;
00354 AddStyle(fPFirst);
00355 }
00356 #if 1
00357 fLoEndPtr = fPLast;
00358 fLoFormStart = fFormStart;
00359 #endif
00360
00361 fFlags |= EXTEND_LAYOUT;
00362 ScheduleRedraw();
00363
00364 return kTRUE;
00365 }
00366
00367
00368 void TGHtml::SetTableRelief(int relief)
00369 {
00370
00371
00372 if (fTableRelief != relief) {
00373 fTableRelief = relief;
00374 fFlags |= RELAYOUT;
00375 RedrawEverything();
00376 }
00377 }
00378
00379
00380 void TGHtml::SetRuleRelief(int relief)
00381 {
00382
00383
00384 if (fRuleRelief != relief) {
00385 fRuleRelief = relief;
00386 fFlags |= RELAYOUT;
00387 RedrawEverything();
00388 }
00389 }
00390
00391
00392 void TGHtml::UnderlineLinks(int onoff)
00393 {
00394
00395
00396 if (fUnderlineLinks != onoff) {
00397 fUnderlineLinks = onoff;
00398
00399
00400
00401 TGHtmlElement *p;
00402 SHtmlStyle_t style = GetCurrentStyle();
00403 for (p = fPFirst; p; p = p->fPNext) {
00404 if (p->fType == Html_A) {
00405 if (fAnchorStart) {
00406 style = PopStyleStack(Html_EndA);
00407 fAnchorStart = 0;
00408 fAnchorFlags = 0;
00409 }
00410 const char *z = p->MarkupArg("href", 0);
00411 if (z) {
00412 style.fColor = GetLinkColor(z);
00413 if (fUnderlineLinks) style.fFlags |= STY_Underline;
00414 fAnchorFlags |= STY_Anchor;
00415 PushStyleStack(Html_EndA, style);
00416 fAnchorStart = (TGHtmlAnchor *) p;
00417 }
00418 } else if (p->fType == Html_EndA) {
00419 if (fAnchorStart) {
00420 ((TGHtmlRef *)p)->fPOther = fAnchorStart;
00421 style = PopStyleStack(Html_EndA);
00422 fAnchorStart = 0;
00423 fAnchorFlags = 0;
00424 }
00425 }
00426 p->fStyle.fFlags &= ~STY_Underline;
00427 p->fStyle.fFlags |= (style.fFlags & STY_Underline);
00428 }
00429
00430 RedrawEverything();
00431 }
00432 }
00433
00434
00435 void TGHtml::SetBaseUri(const char *uri)
00436 {
00437
00438
00439 if (fZBase) delete[] fZBase;
00440 fZBase = 0;
00441 if (uri) fZBase = StrDup(uri);
00442 }
00443
00444
00445 int TGHtml::GotoAnchor(const char *name)
00446 {
00447
00448
00449 const char *z;
00450 TGHtmlElement *p;
00451
00452 for (p = fPFirst; p; p = p->fPNext) {
00453 if (p->fType == Html_A) {
00454 z = p->MarkupArg("name", 0);
00455 if (z && strcmp(z, name) == 0) {
00456 ScrollToPosition(TGLongPosition(fVisible.fX, ((TGHtmlAnchor *)p)->fY));
00457 return kTRUE;
00458 }
00459 }
00460 }
00461
00462 return kFALSE;
00463 }
00464
00465
00466 const char *TGHtml::GetUid(const char *string)
00467 {
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 TObjString *obj = 0;
00481 obj = (TObjString*)fUidTable->FindObject(string);
00482
00483 if (!obj) {
00484 obj = new TObjString(string);
00485 fUidTable->Add(obj);
00486 }
00487
00488 return (const char *)obj->GetName();
00489 }
00490
00491
00492 void TGHtml::ComputeVirtualSize()
00493 {
00494
00495
00496 fVirtualSize = TGDimension(fMaxX, fMaxY);
00497 }
00498
00499
00500 void TGHtml::ClearGcCache()
00501 {
00502
00503
00504 int i;
00505
00506 for (i = 0; i < N_CACHE_GC; i++) {
00507 if (fAGcCache[i].fIndex) {
00508 gVirtualX->DeleteGC(fAGcCache[i].fGc);
00509 fAGcCache[i].fIndex = 0;
00510 }
00511 }
00512 fGcNextToFree = 0;
00513 }
00514
00515
00516 void TGHtml::ResetLayoutContext()
00517 {
00518
00519
00520
00521 fLayoutContext.Reset();
00522 }
00523
00524
00525 void TGHtml::Redraw()
00526 {
00527
00528
00529
00530
00531
00532 Pixmap_t pixmap;
00533 int x, y, w, h;
00534 int hw;
00535 int clipwinH, clipwinW;
00536 TGHtmlBlock *pBlock;
00537 int redoSelection = 0;
00538
00539
00540
00541 if (fInParse) {
00542 fFlags &= ~REDRAW_PENDING;
00543 return;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 if ((fFlags & RESIZE_ELEMENTS) != 0 && (fFlags & STYLER_RUNNING) == 0) {
00556 TGHtmlImage *pImage;
00557 for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
00558 pImage->fPList = 0;
00559 }
00560 fLastSized = 0;
00561 fFlags &= ~RESIZE_ELEMENTS;
00562 fFlags |= RELAYOUT;
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 if ((fFlags & (RELAYOUT | EXTEND_LAYOUT)) != 0
00576 && (fFlags & STYLER_RUNNING) == 0) {
00577 fNextPlaced = 0;
00578
00579 fVarId = 0;
00580 fMaxX = 0;
00581 fMaxY = 0;
00582 ResetLayoutContext();
00583 fFirstBlock = 0;
00584 fLastBlock = 0;
00585 redoSelection = 1;
00586 fFlags &= ~RELAYOUT;
00587 fFlags |= HSCROLL | VSCROLL | REDRAW_TEXT | EXTEND_LAYOUT;
00588 }
00589
00590 if ((fFlags & EXTEND_LAYOUT) && fPFirst != 0) {
00591 LayoutDoc();
00592 fFlags &= ~EXTEND_LAYOUT;
00593 FormBlocks();
00594 MapControls();
00595 if (redoSelection && fSelBegin.fP && fSelEnd.fP) {
00596 UpdateSelection(1);
00597 UpdateInsert();
00598 }
00599 }
00600 fFlags &= ~REDRAW_PENDING;
00601
00602
00603
00604
00605
00606
00607
00608 if ((fFlags & (HSCROLL | VSCROLL)) != 0) {
00609 ComputeVirtualSize();
00610 fFlags &= ~(HSCROLL | VSCROLL);
00611
00612 if (fFlags & REDRAW_PENDING) return;
00613 }
00614
00615
00616 hw = fHighlightWidth;
00617 if (fFlags & REDRAW_FOCUS) {
00618 if (hw > 0) {
00619 #if 0
00620 unsigned long color;
00621
00622 if (fFlags & GOT_FOCUS) {
00623 color = highlightColorPtr;
00624 } else {
00625 color = highlightBgColorPtr;
00626 }
00627 _DrawFocusHighlight(color);
00628 #endif
00629 }
00630 fFlags &= ~REDRAW_FOCUS;
00631 }
00632
00633
00634
00635
00636 if (fFlags & STYLER_RUNNING) {
00637 goto earlyOut;
00638 }
00639
00640 MapControls();
00641
00642
00643
00644
00645 clipwinW = fCanvas->GetWidth();
00646 clipwinH = fCanvas->GetHeight();
00647 if (fFlags & REDRAW_TEXT) {
00648 w = clipwinW;
00649 h = clipwinH;
00650 x = fVisible.fX;
00651 y = fVisible.fY;
00652 fDirtyLeft = 0;
00653 fDirtyTop = 0;
00654 fFlags &= ~REDRAW_TEXT;
00655 } else {
00656 if (fDirtyLeft < 0) fDirtyLeft = 0;
00657 if (fDirtyRight > clipwinW) fDirtyRight = clipwinW;
00658 if (fDirtyTop < 0) fDirtyTop = 0;
00659 if (fDirtyBottom > clipwinH) fDirtyBottom = clipwinH;
00660 w = fDirtyRight - fDirtyLeft;
00661 h = fDirtyBottom - fDirtyTop;
00662 x = fVisible.fX + fDirtyLeft;
00663 y = fVisible.fY + fDirtyTop;
00664 }
00665
00666
00667
00668 if (w > 0 && h > 0) {
00669 GContext_t gcBg;
00670 TGRectangle xrec;
00671
00672
00673
00674 gcBg = GetGC(COLOR_Background, FONT_Any);
00675 pixmap = gVirtualX->CreatePixmap(fCanvas->GetId(), w, h);
00676 xrec.fX = 0;
00677 xrec.fY = 0;
00678 xrec.fW = w;
00679 xrec.fH = h;
00680 #if 0
00681
00682
00683
00684
00685 #else
00686
00687 fWhiteGC.SetTileStipXOrigin(-fVisible.fX - fDirtyLeft);
00688 fWhiteGC.SetTileStipYOrigin(-fVisible.fY - fDirtyTop);
00689
00690 gVirtualX->FillRectangle(pixmap, fWhiteGC.GetGC(), 0, 0, w, h);
00691 UpdateBackgroundStart();
00692 #endif
00693
00694
00695 for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
00696 if (pBlock->fTop <= y+h && pBlock->fBottom >= y-10 &&
00697 pBlock->fLeft <= x+w && pBlock->fRight >= x-10) {
00698 BlockDraw(pBlock, pixmap, x, y, w, h, pixmap);
00699 }
00700 }
00701
00702
00703 gVirtualX->CopyArea(pixmap, fCanvas->GetId(),
00704 gcBg, 0, 0, w, h, fDirtyLeft, fDirtyTop);
00705 gVirtualX->Update(kFALSE);
00706
00707 gVirtualX->DeletePixmap(pixmap);
00708
00709 }
00710
00711
00712 if (fFlags & REDRAW_IMAGES) {
00713 TGHtmlImage *pImage;
00714 TGHtmlImageMarkup *pElem;
00715 int top, bottom, left, right;
00716 int imageTop;
00717
00718 top = fVisible.fY;
00719 bottom = top + fCanvas->GetHeight();
00720 left = fVisible.fX;
00721 right = left + fCanvas->GetWidth();
00722 for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
00723 for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
00724 if (pElem->fRedrawNeeded == 0) continue;
00725 imageTop = pElem->fY - pElem->fAscent;
00726 if (imageTop > bottom || imageTop + pElem->fH < top
00727 || pElem->fX > right || pElem->fX + pElem->fW < left) continue;
00728
00729 DrawImage(pElem, fCanvas->GetId(), left, top, right, bottom);
00730 }
00731 }
00732 fFlags &= ~(REDRAW_IMAGES | ANIMATE_IMAGES);
00733 }
00734
00735
00736 earlyOut:
00737 fDirtyTop = LARGE_NUMBER;
00738 fDirtyLeft = LARGE_NUMBER;
00739 fDirtyBottom = 0;
00740 fDirtyRight = 0;
00741
00742 return;
00743 }
00744
00745
00746 void TGHtml::ScheduleRedraw()
00747 {
00748
00749
00750 if ((fFlags & REDRAW_PENDING) == 0 ) {
00751 if (!fIdle) fIdle = new TGIdleHandler(this);
00752 fFlags |= REDRAW_PENDING;
00753 }
00754 }
00755
00756
00757 Bool_t TGHtml::HandleIdleEvent(TGIdleHandler *idle)
00758 {
00759
00760
00761 if (idle != fIdle) return kFALSE;
00762 Redraw();
00763 delete fIdle;
00764 fIdle = NULL;
00765 return kTRUE;
00766 }
00767
00768
00769 void TGHtml::RedrawArea(int left, int top, int right, int bottom)
00770 {
00771
00772
00773
00774
00775
00776
00777 if (bottom < 0) return;
00778 if (top > (int)fCanvas->GetHeight()) return;
00779 if (right < 0) return;
00780 if (left > (int)fCanvas->GetWidth()) return;
00781 if (fDirtyTop > top) fDirtyTop = top;
00782 if (fDirtyLeft > left) fDirtyLeft = left;
00783 if (fDirtyBottom < bottom) fDirtyBottom = bottom;
00784 if (fDirtyRight < right) fDirtyRight = right;
00785 ScheduleRedraw();
00786 }
00787
00788
00789 void TGHtml::DrawRegion(Int_t x, Int_t y, UInt_t w, UInt_t h)
00790 {
00791
00792
00793 TGView::DrawRegion(x, y, w, h);
00794
00795 #if 0
00796 RedrawArea(x, y, x + w + 1, y + h + 1);
00797 #else
00798 int left = x;
00799 int top = y;
00800 int right = x + w + 1;
00801 int bottom = y + h + 1;
00802 if (bottom < 0) return;
00803 if (top > (int) fCanvas->GetHeight()) return;
00804 if (right < 0) return;
00805 if (left > (int)fCanvas->GetWidth()) return;
00806 if (fDirtyTop > top) fDirtyTop = top;
00807 if (fDirtyLeft > left) fDirtyLeft = left;
00808 if (fDirtyBottom < bottom) fDirtyBottom = bottom;
00809 if (fDirtyRight < right) fDirtyRight = right;
00810
00811 fFlags |= REDRAW_PENDING;
00812 Redraw();
00813 #endif
00814 return;
00815 }
00816
00817
00818 Bool_t TGHtml::ItemLayout()
00819 {
00820
00821
00822 #if 0
00823 fFlags |= RELAYOUT | VSCROLL | HSCROLL;
00824 Redraw();
00825 #else
00826 fNextPlaced = 0;
00827
00828 fVarId = 0;
00829 fMaxX = 0;
00830 fMaxY = 0;
00831 ResetLayoutContext();
00832 fFirstBlock = 0;
00833 fLastBlock = 0;
00834 if (fPFirst != 0) {
00835 LayoutDoc();
00836 FormBlocks();
00837 MapControls();
00838 if (fSelBegin.fP && fSelEnd.fP) {
00839 UpdateSelection(1);
00840 UpdateInsert();
00841 }
00842 }
00843 ComputeVirtualSize();
00844 ScheduleRedraw();
00845 #endif
00846 return kTRUE;
00847 }
00848
00849
00850 void TGHtml::RedrawBlock(TGHtmlBlock *p)
00851 {
00852
00853
00854 if (p) {
00855 RedrawArea(p->fLeft - fVisible.fX, p->fTop - fVisible.fY,
00856 p->fRight - fVisible.fX + 1, p->fBottom - fVisible.fY);
00857 }
00858 }
00859
00860
00861 void TGHtml::RedrawEverything()
00862 {
00863
00864
00865 fFlags |= REDRAW_FOCUS | REDRAW_TEXT;
00866 ScheduleRedraw();
00867 }
00868
00869
00870 void TGHtml::RedrawText(int y)
00871 {
00872
00873
00874
00875 int clipHeight;
00876
00877 clipHeight = fCanvas->GetHeight();
00878 y -= fVisible.fY;
00879 if (y < clipHeight) {
00880 RedrawArea(0, y, LARGE_NUMBER, clipHeight);
00881 }
00882 }
00883
00884
00885 void TGHtml::HClear()
00886 {
00887
00888
00889 int i;
00890 TGHtmlElement *p, *fPNext;
00891
00892 fXMargin = fYMargin = 0;
00893
00894 DeleteControls();
00895 for (p = fPFirst; p; p = fPNext) {
00896 fPNext = p->fPNext;
00897 delete p;
00898 }
00899 fPFirst = 0;
00900 fPLast = 0;
00901 fNToken = 0;
00902 if (fZText) delete[] fZText;
00903 fZText = 0;
00904 fNText = 0;
00905 fNAlloc = 0;
00906 fNComplete = 0;
00907 fIPlaintext = 0;
00908
00909 for (i = 0; i < N_COLOR; ++i) {
00910 if (fApColor[i] != 0) FreeColor(fApColor[i]);
00911 fApColor[i] = 0;
00912 fIDark[i] = 0;
00913 fILight[i] = 0;
00914 }
00915
00916 if (!fExiting) {
00917 fFgColor = AllocColor("black");
00918 fBgColor = AllocColor("white");
00919 fNewLinkColor = AllocColor(DEF_HTML_UNVISITED);
00920 fOldLinkColor = AllocColor(DEF_HTML_VISITED);
00921 fSelectionColor = AllocColor(DEF_HTML_SELECTION_COLOR);
00922
00923 fApColor[COLOR_Normal] = fFgColor;
00924 fApColor[COLOR_Visited] = fOldLinkColor;
00925 fApColor[COLOR_Unvisited] = fNewLinkColor;
00926 fApColor[COLOR_Selection] = fSelectionColor;
00927 fApColor[COLOR_Background] = fBgColor;
00928
00929 SetBackgroundColor(fApColor[COLOR_Background]->fPixel);
00930 SetBackgroundPixmap(0);
00931 }
00932
00933 fColorUsed = 0;
00934 while (fImageList) {
00935 TGHtmlImage *p2 = fImageList;
00936 fImageList = p2->fPNext;
00937 delete p2;
00938 }
00939
00940 if (fBgImage) delete fBgImage;
00941 fBgImage = 0;
00942
00943 while (fStyleStack) {
00944 SHtmlStyleStack_t *p2 = fStyleStack;
00945 fStyleStack = p2->fPNext;
00946 delete p2;
00947 }
00948 ClearGcCache();
00949 ResetLayoutContext();
00950
00951
00952
00953 if (fZBaseHref) delete [] fZBaseHref;
00954 fZBaseHref = 0;
00955 fLastSized = 0;
00956 fNextPlaced = 0;
00957 fFirstBlock = 0;
00958 fLastBlock = 0;
00959 fNInput = 0;
00960 fNForm = 0;
00961 fVarId = 0;
00962 fParaAlignment = ALIGN_None;
00963 fRowAlignment = ALIGN_None;
00964 fAnchorFlags = 0;
00965 fInDt = 0;
00966 fAnchorStart = 0;
00967 fFormStart = 0;
00968 fInnerList = 0;
00969 fMaxX = 0;
00970 fMaxY = 0;
00971 #if 0 // in OXView::Clear()
00972 fVisible = TGPosition(0, 0);
00973 _virtualSize = TGDimension(0, 0);
00974 ScrollTTGPosition(fVisible);
00975 #endif
00976 fPInsBlock = 0;
00977 fIns.fP = 0;
00978 fSelBegin.fP = 0;
00979 fSelEnd.fP = 0;
00980 fPSelStartBlock = 0;
00981 fPSelEndBlock = 0;
00982 fHasScript = 0;
00983 fHasFrames = 0;
00984 fLastUri = 0;
00985 }
00986
00987
00988 Bool_t TGHtml::HandleTimer(TTimer *t)
00989 {
00990
00991
00992 if (t == fInsTimer) {
00993 if (fInsTimer) delete fInsTimer;
00994 fInsTimer = NULL;
00995 FlashCursor();
00996 return kTRUE;
00997 } else {
00998 TGHtmlImage *pImage;
00999 for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
01000 if (pImage->fTimer == t) {
01001 AnimateImage(pImage);
01002 return kTRUE;
01003 }
01004 }
01005 }
01006 return kFALSE;
01007 }
01008
01009
01010 void TGHtml::FlashCursor()
01011 {
01012
01013
01014 if (fPInsBlock == 0 || fInsOnTime <= 0 || fInsOffTime <= 0) return;
01015 RedrawBlock(fPInsBlock);
01016 if ((fFlags & GOT_FOCUS) == 0) {
01017 fInsStatus = 0;
01018 } else if (fInsStatus) {
01019 fInsTimer = new TTimer(this, fInsOffTime);
01020 fInsStatus = 0;
01021 } else {
01022 fInsTimer = new TTimer(this, fInsOnTime);
01023 fInsStatus = 1;
01024 }
01025 }
01026
01027
01028 GContext_t TGHtml::GetGC(int color, int font)
01029 {
01030
01031
01032
01033
01034
01035 int i, j;
01036 GcCache_t *p = fAGcCache;
01037 GCValues_t gcValues;
01038 TGFont *xfont;
01039
01040
01041
01042 if (color < 0 || color >= N_COLOR) color = 0;
01043 if (font < FONT_Any || font >= N_FONT) font = FONT_Default;
01044
01045 for (i = 0; i < N_CACHE_GC; i++, p++) {
01046 if (p->fIndex == 0) continue;
01047 if ((font < 0 || p->fFont == font) && p->fColor == color) {
01048 if (p->fIndex > 1) {
01049 for (j = 0; j < N_CACHE_GC; j++) {
01050 if (fAGcCache[j].fIndex && fAGcCache[j].fIndex < p->fIndex ) {
01051 fAGcCache[j].fIndex++;
01052 }
01053 }
01054 p->fIndex = 1;
01055 }
01056 return fAGcCache[i].fGc;
01057 }
01058 }
01059
01060
01061
01062 p = fAGcCache;
01063 for (i = 0; i < N_CACHE_GC; i++, p++) {
01064 if (p->fIndex == 0 || p->fIndex == N_CACHE_GC) break;
01065 }
01066 if (i >= N_CACHE_GC) {
01067 p = fAGcCache;
01068 for (i = 0; i < N_CACHE_GC && i < fGcNextToFree; ++i, ++p) {}
01069 fGcNextToFree = (fGcNextToFree + 1) % N_CACHE_GC;
01070 gVirtualX->DeleteGC(p->fGc);
01071 }
01072 gcValues.fForeground = fApColor[color]->fPixel;
01073 gcValues.fGraphicsExposures = kTRUE;
01074 gcValues.fMask = kGCForeground | kGCGraphicsExposures;
01075
01076 if (font < 0) font = FONT_Default;
01077 xfont = GetFont(font);
01078
01079 if (xfont) {
01080 gcValues.fFont = xfont->GetFontHandle();
01081 gcValues.fMask |= kGCFont;
01082 }
01083
01084 p->fGc = gVirtualX->CreateGC(fId, &gcValues);
01085
01086 if (p->fIndex == 0) p->fIndex = N_CACHE_GC + 1;
01087 for (j = 0; j < N_CACHE_GC; j++) {
01088 if (fAGcCache[j].fIndex && fAGcCache[j].fIndex < p->fIndex) {
01089 fAGcCache[j].fIndex++;
01090 }
01091 }
01092 p->fIndex = 1;
01093 p->fFont = font;
01094 p->fColor = color;
01095
01096 return p->fGc;
01097 }
01098
01099
01100 GContext_t TGHtml::GetAnyGC()
01101 {
01102
01103
01104
01105 int i;
01106 GcCache_t *p = fAGcCache;
01107
01108 for (i = 0; i < N_CACHE_GC; i++, p++) {
01109 if (p->fIndex) return p->fGc;
01110 }
01111
01112 return GetGC(COLOR_Normal, FONT_Default);
01113 }
01114
01115
01116 Bool_t TGHtml::HandleFocusChange(Event_t *event)
01117 {
01118
01119
01120 if (event->fType == kFocusIn) {
01121 fFlags |= GOT_FOCUS | REDRAW_FOCUS;
01122 ScheduleRedraw();
01123 UpdateInsert();
01124 } else {
01125 fFlags &= ~GOT_FOCUS;
01126 fFlags |= REDRAW_FOCUS;
01127 ScheduleRedraw();
01128 }
01129 return kTRUE;
01130 }
01131
01132
01133 TGHtmlInput *TGHtml::GetInputElement(int x, int y)
01134 {
01135
01136
01137
01138
01139 TGHtmlInput *p;
01140 int vx, vy, vw, vh;
01141
01142 vx = fVisible.fX;
01143 vy = fVisible.fY;
01144 vw = fCanvas->GetWidth();
01145 vh = fCanvas->GetHeight();
01146 for (p = fFirstInput; p; p = p->fINext) {
01147 if (p->fFrame == 0) continue;
01148 if (p->fY < vy + vh && p->fY + p->fH > vy &&
01149 p->fX < vx + vw && p->fX + p->fW > vx) {
01150 if ((x > p->fX) && (y > p->fY) && (x < (p->fX + p->fW)) &&
01151 (y < (p->fY + p->fH)) ) {
01152 return p;
01153 }
01154 }
01155 }
01156 return 0;
01157 }
01158
01159
01160 Bool_t TGHtml::HandleHtmlInput(TGHtmlInput *pr, Event_t *event)
01161 {
01162
01163
01164 Window_t childdum;
01165 Event_t eventSt;
01166 eventSt.fType = event->fType;
01167 eventSt.fWindow = event->fWindow;
01168 eventSt.fTime = event->fTime;
01169 eventSt.fX = 2;
01170 eventSt.fY = 2;
01171 eventSt.fXRoot = event->fXRoot;
01172 eventSt.fYRoot = event->fYRoot;
01173 eventSt.fCode = event->fCode;
01174 eventSt.fState = event->fState;
01175 eventSt.fWidth = event->fWidth;
01176 eventSt.fHeight = event->fHeight;
01177 eventSt.fCount = event->fCount;
01178 eventSt.fSendEvent = event->fSendEvent;
01179 eventSt.fHandle = event->fHandle;
01180 eventSt.fFormat = event->fFormat;
01181 eventSt.fUser[0] = event->fUser[0];
01182 eventSt.fUser[1] = event->fUser[1];
01183 eventSt.fUser[2] = event->fUser[2];
01184 eventSt.fUser[3] = event->fUser[3];
01185 eventSt.fUser[4] = event->fUser[4];
01186 gVirtualX->TranslateCoordinates(GetId(), pr->fFrame->GetId(),
01187 event->fX, event->fY, eventSt.fX,
01188 eventSt.fY, childdum);
01189
01190 const char *name = pr->MarkupArg("name", 0);
01191 const char *val = pr->MarkupArg("value", 0);
01192 switch (pr->fItype) {
01193 case INPUT_TYPE_Submit:
01194 case INPUT_TYPE_Button: {
01195 TGButton *b = (TGButton *) pr->fFrame;
01196 Bool_t was = !b->IsDown();
01197 b->HandleButton(&eventSt);
01198 Bool_t now = !b->IsDown();
01199 if (!was && now) {
01200 if (pr->fItype == INPUT_TYPE_Submit)
01201 SubmitClicked(val);
01202 else
01203 ButtonClicked(name, val);
01204 }
01205 break;
01206 }
01207 case INPUT_TYPE_Radio: {
01208 TGRadioButton *rb = (TGRadioButton *) pr->fFrame;
01209 Bool_t was = !rb->IsDown();
01210 rb->HandleButton(&eventSt);
01211 Bool_t now = !rb->IsDown();
01212 if ((!was && now) || (was && !now)) {
01213 HandleRadioButton(pr);
01214 RadioChanged(name, val);
01215 }
01216 break;
01217 }
01218 case INPUT_TYPE_Checkbox: {
01219 TGCheckButton *cb = (TGCheckButton *) pr->fFrame;
01220 Bool_t was = !cb->IsDown();
01221 cb->HandleButton(&eventSt);
01222 Bool_t now = !cb->IsDown();
01223 if ((!was && now) || (was && !now))
01224 CheckToggled(name, !now, val);
01225 break;
01226 }
01227 case INPUT_TYPE_Text:
01228 case INPUT_TYPE_Password: {
01229 TGTextEntry *te = (TGTextEntry *) pr->fFrame;
01230 te->SetFocus();
01231 break;
01232 }
01233 case INPUT_TYPE_Select: {
01234 RemoveInput(kButtonPressMask | kButtonReleaseMask | kPointerMotionMask);
01235 eventSt.fUser[0] = childdum;
01236 if (pr->fFrame->InheritsFrom("TGComboBox"))
01237 ((TGComboBox *)pr->fFrame)->HandleButton(&eventSt);
01238 else if (pr->fFrame->InheritsFrom("TGListBox"))
01239 ((TGListBox *)pr->fFrame)->HandleButton(&eventSt);
01240 InputSelected(name, val);
01241 AddInput(kButtonPressMask | kButtonReleaseMask | kPointerMotionMask);
01242 break;
01243 }
01244 default:
01245 break;
01246 }
01247 return kTRUE;
01248 }
01249
01250
01251 Bool_t TGHtml::HandleRadioButton(TGHtmlInput *p)
01252 {
01253
01254
01255 TGHtmlInput *pr;
01256 for (pr = fFirstInput; pr; pr = pr->fINext) {
01257 if ((pr->fPForm == p->fPForm) && (pr->fItype == INPUT_TYPE_Radio)) {
01258 if (pr != p) {
01259 if (strcmp(pr->MarkupArg("name", ""), p->MarkupArg("name", "")) == 0) {
01260 ((TGRadioButton *)pr->fFrame)->SetState(kButtonUp);
01261 }
01262 }
01263 }
01264 }
01265
01266 return kTRUE;
01267 }
01268
01269
01270 void TGHtml::ButtonClicked(const char *name, const char *val)
01271 {
01272
01273
01274 Long_t args[2];
01275
01276 args[0] = (Long_t)name;
01277 args[1] = (Long_t)val;
01278
01279 Emit("ButtonClicked(char*,char*)", args);
01280 }
01281
01282
01283 void TGHtml::CheckToggled(const char *name, Bool_t on, const char *val)
01284 {
01285
01286
01287 Long_t args[3];
01288
01289 args[0] = (Long_t)name;
01290 args[1] = on;
01291 args[2] = (Long_t)val;
01292
01293 Emit("CheckToggled(char*,Bool_t,char*)", args);
01294 }
01295
01296
01297 void TGHtml::RadioChanged(const char *name, const char *val)
01298 {
01299
01300
01301 Long_t args[2];
01302
01303 args[0] = (Long_t)name;
01304 args[1] = (Long_t)val;
01305
01306 Emit("RadioChanged(char*,char*)", args);
01307 }
01308
01309
01310 void TGHtml::InputSelected(const char *name, const char *val)
01311 {
01312
01313
01314 Long_t args[2];
01315
01316 args[0] = (Long_t)name;
01317 args[1] = (Long_t)val;
01318
01319 Emit("InputSelected(char*,char*)", args);
01320 }
01321
01322
01323 void TGHtml::SubmitClicked(const char *val)
01324 {
01325
01326
01327 Emit("SubmitClicked(char*)", val);
01328 }
01329
01330
01331 Bool_t TGHtml::HandleButton(Event_t *event)
01332 {
01333
01334
01335 int amount, ch;
01336
01337 ch = fCanvas->GetHeight();
01338 amount = fScrollVal.fY * TMath::Max(ch/6, 1);
01339
01340 int ix = event->fX + fVisible.fX;
01341 int iy = event->fY + fVisible.fY;
01342 TGHtmlInput *pr = GetInputElement(ix, iy);
01343 if (pr) {
01344 HandleHtmlInput(pr, event);
01345 }
01346 if ((event->fType == kButtonPress) && (event->fCode == kButton1)) {
01347 int x = event->fX + fVisible.fX;
01348 int y = event->fY + fVisible.fY;
01349 const char *uri = GetHref(x, y);
01350
01351 #if 0 // insertion cursor test
01352 char ix[20];
01353 sprintf(ix, "begin");
01354 SetInsert(ix);
01355 #endif
01356
01357 if (uri) {
01358 uri = ResolveUri(uri);
01359 if (uri) {
01360 MouseDown(uri);
01361
01362 }
01363 }
01364 } else if (event->fCode == kButton4) {
01365 ScrollToPosition(TGLongPosition(fVisible.fX, fVisible.fY / fScrollVal.fY - amount));
01366 } else if (event->fCode == kButton5) {
01367 ScrollToPosition(TGLongPosition(fVisible.fX, fVisible.fY / fScrollVal.fY + amount));
01368 } else {
01369 return TGView::HandleButton(event);
01370 }
01371 return kTRUE;
01372 }
01373
01374
01375 Bool_t TGHtml::HandleMotion(Event_t *event)
01376 {
01377
01378
01379 int x = event->fX + fVisible.fX;
01380 int y = event->fY + fVisible.fY;
01381 const char *uri = GetHref(x, y);
01382
01383 if (uri) {
01384 gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
01385 } else {
01386 gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
01387 }
01388
01389 if (uri != fLastUri) {
01390 fLastUri = uri;
01391 if (uri) uri = ResolveUri(uri);
01392 MouseOver(uri);
01393
01394 }
01395
01396 return kTRUE;
01397 }
01398
01399
01400 TGFont *TGHtml::GetFont(int iFont)
01401 {
01402
01403
01404
01405
01406 TGFont *toFree = 0;
01407
01408 if (iFont < 0) iFont = 0;
01409 if (iFont >= N_FONT) { iFont = N_FONT - 1; CANT_HAPPEN; }
01410
01411
01412
01413
01414
01415
01416 if (!FontIsValid(iFont) && fAFont[iFont] != 0) {
01417 toFree = fAFont[iFont];
01418 fAFont[iFont] = 0;
01419 }
01420
01421
01422
01423
01424 if (fAFont[iFont] == 0) {
01425 char name[200];
01426 const char *familyStr = "";
01427 int iFamily;
01428 int iSize;
01429 int size;
01430
01431 iFamily = FontFamily(iFont) >> 3;
01432 iSize = FontSize(iFont) + 1;
01433
01434 switch (iFamily) {
01435
01436 #ifdef TIMES
01437 case 0: familyStr = "times -%d"; break;
01438 case 1: familyStr = "times -%d bold"; break;
01439 case 2: familyStr = "times -%d italic"; break;
01440 case 3: familyStr = "times -%d bold italic"; break;
01441 case 4: familyStr = "courier -%d"; break;
01442 case 5: familyStr = "courier -%d bold"; break;
01443 case 6: familyStr = "courier -%d italic"; break;
01444 case 7: familyStr = "courier -%d bold italic"; break;
01445 default: familyStr = "times -16"; CANT_HAPPEN;
01446 #else
01447 case 0: familyStr = "helvetica -%d"; break;
01448 case 1: familyStr = "helvetica -%d bold"; break;
01449 case 2: familyStr = "helvetica -%d italic"; break;
01450 case 3: familyStr = "helvetica -%d bold italic"; break;
01451 case 4: familyStr = "courier -%d"; break;
01452 case 5: familyStr = "courier -%d bold"; break;
01453 case 6: familyStr = "courier -%d italic"; break;
01454 case 7: familyStr = "courier -%d bold italic"; break;
01455 default: familyStr = "helvetica -14"; CANT_HAPPEN;
01456 #endif
01457 }
01458 #if 0
01459 switch (iSize) {
01460 case 1: size = 6+finc; break;
01461 case 2: size = 10+finc; break;
01462 case 3: size = 12+finc; break;
01463 case 4: size = 14+finc; break;
01464 case 5: size = 20+finc; break;
01465 case 6: size = 24+finc; break;
01466 case 7: size = 30+finc; break;
01467 default: size = 14+finc; CANT_HAPPEN;
01468 }
01469 #else
01470 switch (iSize) {
01471 case 1: size = 8; break;
01472 case 2: size = 10; break;
01473 case 3: size = 12; break;
01474 case 4: size = 14; break;
01475 case 5: size = 16; break;
01476 case 6: size = 18; break;
01477 case 7: size = 24; break;
01478 default: size = 14; CANT_HAPPEN;
01479 }
01480 #endif
01481 #ifdef TIMES
01482 if (iFamily < 4) size += 2;
01483 #endif
01484
01485 snprintf(name, 199, familyStr, size);
01486
01487
01488 fAFont[iFont] = fClient->GetFont(name);
01489
01490 if (fAFont[iFont] == 0) {
01491 fprintf(stderr, "TGHtml: could not get font \"%s\", trying fixed\n",
01492 name);
01493 fAFont[iFont] = fClient->GetFont("fixed");
01494 }
01495 if (fAFont[iFont] == 0 ){
01496 fprintf(stderr, "TGHtml: could not get font \"fixed\", trying "
01497 "\"helvetica -12\"\n");
01498 fAFont[iFont] = fClient->GetFont("helvetica -12");
01499 }
01500 FontSetValid(iFont);
01501 }
01502
01503
01504
01505 if (toFree) fClient->FreeFont(toFree);
01506
01507 return fAFont[iFont];
01508 }
01509
01510
01511 int TGHtml::InArea(TGHtmlMapArea *p, int left, int top, int x, int y)
01512 {
01513
01514
01515 int *ip = p->fCoords;
01516 if (!ip) return 0;
01517
01518 if (p->fMType == HTML_MAP_RECT) {
01519 return ((left + ip[0]) <= x && (left + ip[2]) >= x &&
01520 (top + ip[1]) <= y && (top + ip[3]) >= y);
01521 } else if (p->fMType == HTML_MAP_CIRCLE) {
01522 int dx = left + ip[0] - x;
01523 int dy = top + ip[1] - y;
01524 return (dx * dx + dy * dy <= ip[2] * ip[2]);
01525 }
01526 return 0;
01527 }
01528
01529
01530 TGHtmlElement *TGHtml::GetMap(const char *name)
01531 {
01532
01533
01534 TGHtmlElement *p = fPFirst;
01535 const char *z, *zb;
01536
01537 while (p) {
01538 if (p->fType == Html_MAP) {
01539 z = p->MarkupArg("name", 0);
01540 zb = p->MarkupArg("shape", 0);
01541 if (zb && *zb != 'r') return 0;
01542 if (z && !strcmp(z, name)) return p;
01543 }
01544 p = p->fPNext;
01545 }
01546 return 0;
01547 }
01548
01549
01550 float TGHtml::ColorDistance(ColorStruct_t *pA, ColorStruct_t *pB)
01551 {
01552
01553
01554 float x, y, z;
01555
01556 x = 0.30 * (pA->fRed - pB->fRed);
01557 y = 0.61 * (pA->fGreen - pB->fGreen);
01558 z = 0.11 * (pA->fBlue - pB->fBlue);
01559
01560 return x*x + y*y + z*z;
01561 }
01562
01563
01564 int TGHtml::GetColorByName(const char *zColor)
01565 {
01566
01567
01568
01569
01570 ColorStruct_t *pNew;
01571 int iColor;
01572 const char *name;
01573 int i, n;
01574 char zAltColor[16];
01575
01576
01577
01578
01579
01580 n = strlen(zColor);
01581 if (n == 6 || n == 3 || n == 9 || n == 12) {
01582 for (i = 0; i < n; i++) {
01583 if (!isxdigit(zColor[i])) break;
01584 }
01585 if (i == n) {
01586 snprintf(zAltColor, 15, "#%s", zColor);
01587 } else {
01588 strlcpy(zAltColor, zColor, sizeof(zAltColor));
01589 }
01590 name = GetUid(zAltColor);
01591 } else {
01592 name = GetUid(zColor);
01593 }
01594
01595 pNew = AllocColor(name);
01596 if (pNew == 0) {
01597 return 0;
01598 }
01599
01600 iColor = GetColorByValue(pNew);
01601 FreeColor(pNew);
01602
01603 return iColor;
01604 }
01605
01606
01607
01608
01609 #define MAX_COLOR 65535
01610 #define MAX(A,B) ((A)<(B)?(B):(A))
01611 #define MIN(A,B) ((A)<(B)?(A):(B))
01612
01613
01614 int TGHtml::IsDarkColor(ColorStruct_t *p)
01615 {
01616
01617
01618
01619 float x, y, z;
01620
01621 x = 0.50 * p->fRed;
01622 y = 1.00 * p->fGreen;
01623 z = 0.28 * p->fBlue;
01624 return (x*x + y*y + z*z) < (0.05 * MAX_COLOR * MAX_COLOR);
01625 }
01626
01627
01628 int TGHtml::GetDarkShadowColor(int iBgColor)
01629 {
01630
01631
01632
01633 if (fIDark[iBgColor] == 0) {
01634 ColorStruct_t *pRef, val;
01635 pRef = fApColor[iBgColor];
01636 if (IsDarkColor(pRef)) {
01637 int t1, t2;
01638 t1 = (int) MIN(MAX_COLOR, pRef->fRed * 1.2);
01639 t2 = (pRef->fRed * 3 + MAX_COLOR) / 4;
01640 val.fRed = MAX(t1, t2);
01641 t1 = (int) MIN(MAX_COLOR, pRef->fGreen * 1.2);
01642 t2 = (pRef->fGreen * 3 + MAX_COLOR) / 4;
01643 val.fGreen = MAX(t1, t2);
01644 t1 = (int) MIN(MAX_COLOR, pRef->fBlue * 1.2);
01645 t2 = (pRef->fBlue * 3 + MAX_COLOR) / 4;
01646 val.fBlue = MAX(t1, t2);
01647 } else {
01648 val.fRed = (unsigned short) (pRef->fRed * 0.6);
01649 val.fGreen = (unsigned short) (pRef->fGreen * 0.6);
01650 val.fBlue = (unsigned short) (pRef->fBlue * 0.6);
01651 }
01652 fIDark[iBgColor] = GetColorByValue(&val) + 1;
01653 }
01654
01655 return fIDark[iBgColor] - 1;
01656 }
01657
01658
01659 int TGHtml::IsLightColor(ColorStruct_t *p)
01660 {
01661
01662
01663
01664 return p->fGreen >= 0.85 * MAX_COLOR;
01665 }
01666
01667
01668 int TGHtml::GetLightShadowColor(int iBgColor)
01669 {
01670
01671
01672
01673 if (fILight[iBgColor] == 0) {
01674 ColorStruct_t *pRef, val;
01675 pRef = fApColor[iBgColor];
01676 if (IsLightColor(pRef)) {
01677 val.fRed = (unsigned short) (pRef->fRed * 0.9);
01678 val.fGreen = (unsigned short) (pRef->fGreen * 0.9);
01679 val.fBlue = (unsigned short) (pRef->fBlue * 0.9);
01680 } else {
01681 int t1, t2;
01682 t1 = (int) MIN(MAX_COLOR, pRef->fGreen * 1.4);
01683 t2 = (pRef->fGreen + MAX_COLOR) / 2;
01684 val.fGreen = MAX(t1, t2);
01685 t1 = (int) MIN(MAX_COLOR, pRef->fRed * 1.4);
01686 t2 = (pRef->fRed + MAX_COLOR) / 2;
01687 val.fRed = MAX(t1, t2);
01688 t1 = (int) MIN(MAX_COLOR, pRef->fBlue * 1.4);
01689 t2 = (pRef->fBlue + MAX_COLOR) / 2;
01690 val.fBlue = MAX(t1, t2);
01691 }
01692 fILight[iBgColor] = GetColorByValue(&val) + 1;
01693 }
01694
01695 return fILight[iBgColor] - 1;
01696 }
01697
01698
01699 int TGHtml::GetColorByValue(ColorStruct_t *pRef)
01700 {
01701
01702
01703
01704 int i;
01705 float dist;
01706 float closestDist;
01707 int closest;
01708 int r, g, b;
01709 # define COLOR_MASK 0xf800
01710
01711
01712 r = pRef->fRed & COLOR_MASK;
01713 g = pRef->fGreen & COLOR_MASK;
01714 b = pRef->fBlue & COLOR_MASK;
01715 for (i = 0; i < N_COLOR; i++) {
01716 ColorStruct_t *p = fApColor[i];
01717 if (p &&
01718 ((p->fRed & COLOR_MASK) == r) &&
01719 ((p->fGreen & COLOR_MASK) == g) &&
01720 ((p->fBlue & COLOR_MASK) == b)) {
01721 fColorUsed |= (1<<i);
01722 return i;
01723 }
01724 }
01725
01726
01727 for (i = N_PREDEFINED_COLOR; i < N_COLOR; i++) {
01728 if (fApColor[i] == 0) {
01729 fApColor[i] = AllocColorByValue(pRef);
01730 fColorUsed |= (1<<i);
01731 return i;
01732 }
01733 }
01734
01735
01736
01737 for (i = N_PREDEFINED_COLOR; i < N_COLOR; i++) {
01738 if (((fColorUsed >> i) & 1) == 0) {
01739 FreeColor(fApColor[i]);
01740 fApColor[i] = AllocColorByValue(pRef);
01741 fColorUsed |= (1<<i);
01742 return i;
01743 }
01744 }
01745
01746
01747
01748 closest = 0;
01749 closestDist = ColorDistance(pRef, fApColor[0]);
01750 for (i = 1; i < N_COLOR; i++) {
01751 dist = ColorDistance(pRef, fApColor[i]);
01752 if (dist < closestDist) {
01753 closestDist = dist;
01754 closest = i;
01755 }
01756 }
01757
01758 return closest;
01759 }
01760
01761
01762 const char *TGHtml::GetHref(int x, int y, const char **target)
01763 {
01764
01765
01766
01767
01768 TGHtmlBlock *pBlock;
01769 TGHtmlElement *pElem;
01770
01771 for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
01772 if (pBlock->fTop > y || pBlock->fBottom < y ||
01773 pBlock->fLeft > x || pBlock->fRight < x) continue;
01774 pElem = pBlock->fPNext;
01775 if (pElem->fType == Html_IMG) {
01776 TGHtmlImageMarkup *image = (TGHtmlImageMarkup *) pElem;
01777 if (image->fPMap) {
01778 pElem = image->fPMap->fPNext;
01779 while (pElem && pElem->fType != Html_EndMAP) {
01780 if (pElem->fType == Html_AREA) {
01781 if (InArea((TGHtmlMapArea *) pElem, pBlock->fLeft, pBlock->fTop, x, y)) {
01782 if (target) *target = pElem->MarkupArg("target", 0);
01783 return pElem->MarkupArg("href", 0);
01784 }
01785 }
01786 pElem = pElem->fPNext;
01787 }
01788 continue;
01789 }
01790 }
01791 if ((pElem->fStyle.fFlags & STY_Anchor) == 0) continue;
01792 switch (pElem->fType) {
01793 case Html_Text:
01794 case Html_Space:
01795 case Html_IMG:
01796 while (pElem && pElem->fType != Html_A) pElem = pElem->fPPrev;
01797 if (pElem == 0 || pElem->fType != Html_A) break;
01798 if (target) *target = pElem->MarkupArg("target", 0);
01799 return pElem->MarkupArg("href", 0);
01800
01801 default:
01802 break;
01803 }
01804 }
01805
01806 return 0;
01807 }
01808
01809
01810 int TGHtml::ElementCoords(TGHtmlElement *p, int , int pct, int *coords)
01811 {
01812
01813
01814 TGHtmlBlock *pBlock;
01815
01816 while (p && p->fType != Html_Block) p = p->fPPrev;
01817 if (!p) return 1;
01818
01819 pBlock = (TGHtmlBlock *) p;
01820 if (pct) {
01821 TGHtmlElement *pEnd = fPLast;
01822 TGHtmlBlock *pb2;
01823 while (pEnd && pEnd->fType != Html_Block) pEnd = pEnd->fPPrev;
01824 pb2 = (TGHtmlBlock *) pEnd;
01825 #define HGCo(dir) (pb2 && pb2->dir) ? pBlock->dir * 100 / pb2->dir : 0
01826 coords[0] = HGCo(fLeft);
01827 coords[1] = HGCo(fTop);
01828 coords[3] = HGCo(fRight);
01829 coords[4] = HGCo(fBottom);
01830 } else {
01831 coords[0] = pBlock->fLeft;
01832 coords[1] = pBlock->fTop;
01833 coords[2] = pBlock->fRight;
01834 coords[3] = pBlock->fBottom;
01835 }
01836 return 0;
01837 }
01838
01839
01840 TGHtmlElement *TGHtml::AttrElem(const char *name, char *value)
01841 {
01842
01843
01844 TGHtmlElement *p;
01845 const char *z;
01846
01847 for (p = fPFirst; p; p = p->fPNext) {
01848 if (p->fType != Html_A) continue;
01849 z = p->MarkupArg(name, 0);
01850 if (z && (strcmp(z, value) == 0)) return p;
01851 }
01852 return 0;
01853 }
01854
01855
01856 void TGHtml::UpdateSelection(int forceUpdate)
01857 {
01858
01859
01860
01861
01862
01863
01864
01865 TGHtmlBlock *pBlock;
01866 int index;
01867 int needUpdate = forceUpdate;
01868 int temp;
01869
01870 if (fSelEnd.fP == 0) fSelBegin.fP = 0;
01871
01872 IndexToBlockIndex(fSelBegin, &pBlock, &index);
01873 if (needUpdate || pBlock != fPSelStartBlock) {
01874 needUpdate = 1;
01875 RedrawBlock(fPSelStartBlock);
01876 fPSelStartBlock = pBlock;
01877 fSelStartIndex = index;
01878 } else if (index != fSelStartIndex) {
01879 RedrawBlock(pBlock);
01880 fSelStartIndex = index;
01881 }
01882
01883 if (fSelBegin.fP == 0) fSelEnd.fP = 0;
01884
01885 IndexToBlockIndex(fSelEnd, &pBlock, &index);
01886 if (needUpdate || pBlock != fPSelEndBlock) {
01887 needUpdate = 1;
01888 RedrawBlock(fPSelEndBlock);
01889 fPSelEndBlock = pBlock;
01890 fSelEndIndex = index;
01891 } else if (index != fSelEndIndex) {
01892 RedrawBlock(pBlock);
01893 fSelEndIndex = index;
01894 }
01895
01896 if (fPSelStartBlock && fPSelStartBlock == fPSelEndBlock &&
01897 fSelStartIndex > fSelEndIndex) {
01898 temp = fSelStartIndex;
01899 fSelStartIndex = fSelEndIndex;
01900 fSelEndIndex = temp;
01901 }
01902
01903 if (needUpdate) {
01904 fFlags |= ANIMATE_IMAGES;
01905 UpdateSelectionDisplay();
01906 }
01907 }
01908
01909
01910 void TGHtml::UpdateSelectionDisplay()
01911 {
01912
01913
01914
01915
01916
01917
01918 int selected = 0;
01919 SHtmlIndex_t tempIndex;
01920 TGHtmlBlock *pTempBlock;
01921 int temp;
01922 TGHtmlBlock *p;
01923
01924 for (p = fFirstBlock; p; p = p->fBNext) {
01925 if (p == fPSelStartBlock) {
01926 selected = 1;
01927 RedrawBlock(p);
01928 } else if (!selected && p == fPSelEndBlock) {
01929 selected = 1;
01930 tempIndex = fSelBegin;
01931 fSelBegin = fSelEnd;
01932 fSelEnd = tempIndex;
01933 pTempBlock = fPSelStartBlock;
01934 fPSelStartBlock = fPSelEndBlock;
01935 fPSelEndBlock = pTempBlock;
01936 temp = fSelStartIndex;
01937 fSelStartIndex = fSelEndIndex;
01938 fSelEndIndex = temp;
01939 RedrawBlock(p);
01940 }
01941 if (p->fFlags & HTML_Selected) {
01942 if (!selected) {
01943 p->fFlags &= ~HTML_Selected;
01944 RedrawBlock(p);
01945 }
01946 } else {
01947 if (selected) {
01948 p->fFlags |= HTML_Selected;
01949 RedrawBlock(p);
01950 }
01951 }
01952 if (p == fPSelEndBlock) {
01953 selected = 0;
01954 RedrawBlock(p);
01955 }
01956 }
01957 }
01958
01959
01960 void TGHtml::LostSelection()
01961 {
01962
01963
01964 if (fExportSelection) {
01965
01966 fPSelStartBlock = 0;
01967 fPSelEndBlock = 0;
01968 fSelBegin.fP = 0;
01969 fSelEnd.fP = 0;
01970 UpdateSelectionDisplay();
01971 }
01972 }
01973
01974
01975 int TGHtml::SelectionSet(const char *startIx, const char *endIx)
01976 {
01977
01978
01979 SHtmlIndex_t sBegin, sEnd;
01980 int bi, ei;
01981
01982 if (GetIndex(startIx, &sBegin.fP, &sBegin.fI)) {
01983
01984 return kFALSE;
01985 }
01986
01987 if (GetIndex(endIx, &sEnd.fP, &sEnd.fI)) {
01988
01989 return kFALSE;
01990 }
01991
01992 bi = TokenNumber(sBegin.fP);
01993 ei = TokenNumber(sEnd.fP);
01994
01995 if (!(sBegin.fP && sEnd.fP)) return kTRUE;
01996
01997 if (bi < ei || (bi == ei && sBegin.fI <= sEnd.fI)) {
01998 fSelBegin = sBegin;
01999 fSelEnd = sEnd;
02000 } else {
02001 fSelBegin = sEnd;
02002 fSelEnd = sBegin;
02003 }
02004
02005 UpdateSelection(0);
02006 if (fExportSelection) {
02007
02008
02009
02010 }
02011
02012 return kTRUE;
02013 }
02014
02015
02016 void TGHtml::UpdateInsert()
02017 {
02018
02019
02020
02021 IndexToBlockIndex(fIns, &fPInsBlock, &fInsIndex);
02022 RedrawBlock(fPInsBlock);
02023 if (fInsTimer == 0) {
02024 fInsStatus = 0;
02025 FlashCursor();
02026 }
02027 }
02028
02029
02030 int TGHtml::SetInsert(const char *insIx)
02031 {
02032
02033
02034 SHtmlIndex_t i;
02035
02036 if (!insIx) {
02037 RedrawBlock(fPInsBlock);
02038 fInsStatus = 0;
02039 fPInsBlock = 0;
02040 fIns.fP = 0;
02041 } else {
02042 if (GetIndex(insIx, &i.fP, &i.fI)) {
02043
02044 return kFALSE;
02045 }
02046 RedrawBlock(fPInsBlock);
02047 fIns = i;
02048 UpdateInsert();
02049 }
02050
02051 return kTRUE;
02052 }
02053
02054
02055 void TGHtml::SavePrimitive(ostream &out, Option_t *option )
02056 {
02057
02058
02059 out << " TGHtml *";
02060 out << GetName() << " = new TGHtml(" << fParent->GetName()
02061 << "," << GetWidth() << "," << GetHeight()
02062 << ");"<< endl;
02063 if (option && strstr(option, "keep_names"))
02064 out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
02065
02066 if (fCanvas->GetBackground() != TGFrame::GetWhitePixel()) {
02067 out << " " << GetName() << "->ChangeBackground(" << fCanvas->GetBackground() << ");" << endl;
02068 }
02069
02070 TString fn;
02071 TGText txt(GetText());
02072 fn.Form("Html%s.htm", GetName()+5);
02073 txt.Save(fn.Data());
02074 out << " " << "FILE *f = fopen(\"" << fn.Data() << "\", \"r\");" << endl;
02075 out << " " << "if (f) {" << endl;
02076 out << " " << GetName() << "->Clear();" << endl;
02077 out << " " << GetName() << "->Layout();" << endl;
02078 out << " " << GetName() << "->SetBaseUri(\"\");" << endl;
02079 out << " " << "char *buf = (char *)calloc(4096, sizeof(char));" << endl;
02080 out << " " << "while (fgets(buf, 4096, f)) {" << endl;
02081 out << " " << GetName() << "->ParseText(buf);" << endl;
02082 out << " " << "}" << endl;
02083 out << " " << "free(buf);" << endl;
02084 out << " " << "fclose(f);" << endl;
02085 out << " " << "}" << endl;
02086 out << " " << GetName() << "->Layout();" << endl;
02087 }