60 int HtmlTraceMask = 0;
63 #define DEF_FRAME_BG_COLOR "#c0c0c0"
64 #define DEF_FRAME_CURSOR ""
65 #define DEF_BUTTON_FG "black"
66 #define DEF_BUTTON_HIGHLIGHT_BG "#d9d9d9"
67 #define DEF_BUTTON_HIGHLIGHT "black"
73 TGHtml::TGHtml(
const TGWindow *p,
int w,
int h,
int id) : TGView(p, w, h, id)
100 fInsOnTime = DEF_HTML_INSERT_ON_TIME;
101 fInsOffTime = DEF_HTML_INSERT_OFF_TIME;
117 fParaAlignment = ALIGN_None;
118 fRowAlignment = ALIGN_None;
130 ResetLayoutContext();
132 fHighlightBgColorPtr = 0;
133 fHighlightColorPtr = 0;
134 for (i = 0; i < N_FONT; ++i) fAFont[i] = 0;
135 memset(fFontValid, 0,
sizeof(fFontValid));
136 for (i = 0; i < N_COLOR; ++i) {
141 fFgColor = AllocColor(
"black");
142 fBgColor = AllocColor(
"white");
143 fNewLinkColor = AllocColor(DEF_HTML_UNVISITED);
144 fOldLinkColor = AllocColor(DEF_HTML_VISITED);
145 fSelectionColor = AllocColor(DEF_HTML_SELECTION_COLOR);
147 fApColor[COLOR_Normal] = fFgColor;
148 fApColor[COLOR_Visited] = fOldLinkColor;
149 fApColor[COLOR_Unvisited] = fNewLinkColor;
150 fApColor[COLOR_Selection] = fSelectionColor;
151 fApColor[COLOR_Background] = fBgColor;
155 SetBackgroundColor(fApColor[COLOR_Background]->fPixel);
156 SetBackgroundPixmap(0);
160 for (i = 0; i < N_CACHE_GC; ++i) {
161 fAGcCache[i].fIndex = 0;
162 fAGcCache[i].fColor = 0;
163 fAGcCache[i].fFont = 0;
164 fAGcCache[i].fGc = 0;
185 fUnderlineLinks = kTRUE;
186 fExportSelection = DEF_HTML_EXPORT_SEL;
187 fTableRelief = HTML_RELIEF_RAISED;
188 fRuleRelief = HTML_RELIEF_SUNKEN;
196 fXMargin = fYMargin = 0;
198 fFlags = RESIZE_ELEMENTS | RELAYOUT;
200 fDirtyLeft = LARGE_NUMBER;
202 fDirtyTop = LARGE_NUMBER;
206 fVsb->SetAccelerated();
207 fHsb->SetAccelerated();
211 AddInput(kExposureMask | kFocusChangeMask);
212 AddInput(kButtonPressMask | kButtonReleaseMask | kPointerMotionMask);
214 fUidTable =
new THashTable(100);
226 for (i = 0; i < N_FONT; i++) {
227 if (fAFont[i] != 0) fClient->FreeFont(fAFont[i]);
229 if (fInsTimer)
delete fInsTimer;
230 if (fIdle)
delete fIdle;
238 void TGHtml::UpdateBackgroundStart()
251 void TGHtml::FreeColor(ColorStruct_t *color)
253 gVirtualX->FreeColor(gClient->GetDefaultColormap(), color->fPixel);
260 ColorStruct_t *TGHtml::AllocColor(
const char *name)
262 ColorStruct_t *color =
new ColorStruct_t;
265 if (gVirtualX->ParseColor(fClient->GetDefaultColormap(), name, *color)) {
266 if (!gVirtualX->AllocColor(fClient->GetDefaultColormap(), *color)) {
268 gVirtualX->QueryColor(fClient->GetDefaultColormap(), *color);
269 gVirtualX->AllocColor(fClient->GetDefaultColormap(), *color);
279 ColorStruct_t *TGHtml::AllocColorByValue(ColorStruct_t *color)
281 ColorStruct_t *c =
new ColorStruct_t;
284 if (!gVirtualX->AllocColor(gClient->GetDefaultColormap(), *c)) {
287 gVirtualX->QueryColor(gClient->GetDefaultColormap(), *c);
288 gVirtualX->AllocColor(gClient->GetDefaultColormap(), *c);
298 void TGHtml::Clear(Option_t *)
302 fFlags |= REDRAW_TEXT | VSCROLL | HSCROLL;
313 int TGHtml::ParseText(
char *text,
const char *index)
316 TGHtmlElement *savePtr=0;
324 int rc = GetIndex(index, &iStart.fP, &iStart.fI);
325 if (rc != 0)
return kFALSE;
327 savePtr = iStart.fP->fPNext;
329 iStart.fP->fPNext = 0;
333 TokenizerAppend(text);
336 fFormStart = fLoFormStart;
337 if (iStart.fP && savePtr) {
339 fPLast->fPNext = savePtr;
340 savePtr->fPPrev = fPLast;
342 fFlags |= REDRAW_TEXT | RELAYOUT;
344 }
else if (fLoEndPtr->fPNext) {
345 AddStyle(fLoEndPtr->fPNext);
347 }
else if (fPFirst) {
348 fParaAlignment = ALIGN_None;
349 fRowAlignment = ALIGN_None;
360 fLoFormStart = fFormStart;
363 fFlags |= EXTEND_LAYOUT;
372 void TGHtml::SetTableRelief(
int relief)
374 if (fTableRelief != relief) {
375 fTableRelief = relief;
384 void TGHtml::SetRuleRelief(
int relief)
386 if (fRuleRelief != relief) {
387 fRuleRelief = relief;
396 void TGHtml::UnderlineLinks(
int onoff)
398 if (fUnderlineLinks != onoff) {
399 fUnderlineLinks = onoff;
404 SHtmlStyle_t style = GetCurrentStyle();
405 for (p = fPFirst; p; p = p->fPNext) {
406 if (p->fType == Html_A) {
408 style = PopStyleStack(Html_EndA);
412 const char *z = p->MarkupArg(
"href", 0);
414 style.fColor = GetLinkColor(z);
415 if (fUnderlineLinks) style.fFlags |= STY_Underline;
416 fAnchorFlags |= STY_Anchor;
417 PushStyleStack(Html_EndA, style);
418 fAnchorStart = (TGHtmlAnchor *) p;
420 }
else if (p->fType == Html_EndA) {
422 ((TGHtmlRef *)p)->fPOther = fAnchorStart;
423 style = PopStyleStack(Html_EndA);
428 p->fStyle.fFlags &= ~STY_Underline;
429 p->fStyle.fFlags |= (style.fFlags & STY_Underline);
439 void TGHtml::SetBaseUri(
const char *uri)
441 if (fZBase)
delete[] fZBase;
443 if (uri) fZBase = StrDup(uri);
449 int TGHtml::GotoAnchor(
const char *name)
454 for (p = fPFirst; p; p = p->fPNext) {
455 if (p->fType == Html_A) {
456 z = p->MarkupArg(
"name", 0);
457 if (z && strcmp(z, name) == 0) {
458 ScrollToPosition(TGLongPosition(fVisible.fX, ((TGHtmlAnchor *)p)->fY));
478 const char *TGHtml::GetUid(
const char *
string)
483 obj = (TObjString*)fUidTable->FindObject(
string);
486 obj =
new TObjString(
string);
490 return (
const char *)obj->GetName();
496 void TGHtml::ComputeVirtualSize()
498 fVirtualSize = TGDimension(fMaxX, fMaxY);
504 void TGHtml::ClearGcCache()
508 for (i = 0; i < N_CACHE_GC; i++) {
509 if (fAGcCache[i].fIndex) {
510 gVirtualX->DeleteGC(fAGcCache[i].fGc);
511 fAGcCache[i].fIndex = 0;
521 void TGHtml::ResetLayoutContext()
523 fLayoutContext.Reset();
532 void TGHtml::Redraw()
537 int clipwinH, clipwinW;
539 int redoSelection = 0;
544 fFlags &= ~REDRAW_PENDING;
557 if ((fFlags & RESIZE_ELEMENTS) != 0 && (fFlags & STYLER_RUNNING) == 0) {
559 for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
563 fFlags &= ~RESIZE_ELEMENTS;
577 if ((fFlags & (RELAYOUT | EXTEND_LAYOUT)) != 0
578 && (fFlags & STYLER_RUNNING) == 0) {
584 ResetLayoutContext();
589 fFlags |= HSCROLL | VSCROLL | REDRAW_TEXT | EXTEND_LAYOUT;
592 if ((fFlags & EXTEND_LAYOUT) && fPFirst != 0) {
594 fFlags &= ~EXTEND_LAYOUT;
597 if (redoSelection && fSelBegin.fP && fSelEnd.fP) {
602 fFlags &= ~REDRAW_PENDING;
610 if ((fFlags & (HSCROLL | VSCROLL)) != 0) {
611 ComputeVirtualSize();
612 fFlags &= ~(HSCROLL | VSCROLL);
614 if (fFlags & REDRAW_PENDING)
return;
618 hw = fHighlightWidth;
619 if (fFlags & REDRAW_FOCUS) {
624 if (fFlags & GOT_FOCUS) {
625 color = highlightColorPtr;
627 color = highlightBgColorPtr;
629 _DrawFocusHighlight(color);
632 fFlags &= ~REDRAW_FOCUS;
638 if (fFlags & STYLER_RUNNING) {
647 clipwinW = fCanvas->GetWidth();
648 clipwinH = fCanvas->GetHeight();
649 if (fFlags & REDRAW_TEXT) {
656 fFlags &= ~REDRAW_TEXT;
658 if (fDirtyLeft < 0) fDirtyLeft = 0;
659 if (fDirtyRight > clipwinW) fDirtyRight = clipwinW;
660 if (fDirtyTop < 0) fDirtyTop = 0;
661 if (fDirtyBottom > clipwinH) fDirtyBottom = clipwinH;
662 w = fDirtyRight - fDirtyLeft;
663 h = fDirtyBottom - fDirtyTop;
664 x = fVisible.fX + fDirtyLeft;
665 y = fVisible.fY + fDirtyTop;
670 if (w > 0 && h > 0) {
676 gcBg = GetGC(COLOR_Background, FONT_Any);
677 pixmap = gVirtualX->CreatePixmap(fCanvas->GetId(), w, h);
689 fWhiteGC.SetTileStipXOrigin(-fVisible.fX - fDirtyLeft);
690 fWhiteGC.SetTileStipYOrigin(-fVisible.fY - fDirtyTop);
692 gVirtualX->FillRectangle(pixmap, fWhiteGC.GetGC(), 0, 0, w, h);
693 UpdateBackgroundStart();
697 for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
698 if (pBlock->fTop <= y+h && pBlock->fBottom >= y-10 &&
699 pBlock->fLeft <= x+w && pBlock->fRight >= x-10) {
700 BlockDraw(pBlock, pixmap, x, y, w, h, pixmap);
705 gVirtualX->CopyArea(pixmap, fCanvas->GetId(),
706 gcBg, 0, 0, w, h, fDirtyLeft, fDirtyTop);
707 gVirtualX->Update(kFALSE);
709 gVirtualX->DeletePixmap(pixmap);
714 if (fFlags & REDRAW_IMAGES) {
716 TGHtmlImageMarkup *pElem;
717 int top, bottom, left, right;
721 bottom = top + fCanvas->GetHeight();
723 right = left + fCanvas->GetWidth();
724 for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
725 for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
726 if (pElem->fRedrawNeeded == 0)
continue;
727 imageTop = pElem->fY - pElem->fAscent;
728 if (imageTop > bottom || imageTop + pElem->fH < top
729 || pElem->fX > right || pElem->fX + pElem->fW < left)
continue;
731 DrawImage(pElem, fCanvas->GetId(), left, top, right, bottom);
734 fFlags &= ~(REDRAW_IMAGES | ANIMATE_IMAGES);
739 fDirtyTop = LARGE_NUMBER;
740 fDirtyLeft = LARGE_NUMBER;
750 void TGHtml::ScheduleRedraw()
752 if ((fFlags & REDRAW_PENDING) == 0 ) {
753 if (!fIdle) fIdle =
new TGIdleHandler(
this);
754 fFlags |= REDRAW_PENDING;
761 Bool_t TGHtml::HandleIdleEvent(TGIdleHandler *idle)
763 if (idle != fIdle)
return kFALSE;
777 void TGHtml::RedrawArea(
int left,
int top,
int right,
int bottom)
779 if (bottom < 0)
return;
780 if (top > (
int)fCanvas->GetHeight())
return;
781 if (right < 0)
return;
782 if (left > (
int)fCanvas->GetWidth())
return;
783 if (fDirtyTop > top) fDirtyTop = top;
784 if (fDirtyLeft > left) fDirtyLeft = left;
785 if (fDirtyBottom < bottom) fDirtyBottom = bottom;
786 if (fDirtyRight < right) fDirtyRight = right;
793 void TGHtml::DrawRegion(Int_t x, Int_t y, UInt_t w, UInt_t h)
795 TGView::DrawRegion(x, y, w, h);
798 RedrawArea(x, y, x + w + 1, y + h + 1);
802 int right = x + w + 1;
803 int bottom = y + h + 1;
804 if (bottom < 0)
return;
805 if (top > (
int) fCanvas->GetHeight())
return;
806 if (right < 0)
return;
807 if (left > (
int)fCanvas->GetWidth())
return;
808 if (fDirtyTop > top) fDirtyTop = top;
809 if (fDirtyLeft > left) fDirtyLeft = left;
810 if (fDirtyBottom < bottom) fDirtyBottom = bottom;
811 if (fDirtyRight < right) fDirtyRight = right;
813 fFlags |= REDRAW_PENDING;
822 Bool_t TGHtml::ItemLayout()
825 fFlags |= RELAYOUT | VSCROLL | HSCROLL;
833 ResetLayoutContext();
840 if (fSelBegin.fP && fSelEnd.fP) {
845 ComputeVirtualSize();
854 void TGHtml::RedrawBlock(TGHtmlBlock *p)
857 RedrawArea(p->fLeft - fVisible.fX, p->fTop - fVisible.fY,
858 p->fRight - fVisible.fX + 1, p->fBottom - fVisible.fY);
865 void TGHtml::RedrawEverything()
867 fFlags |= REDRAW_FOCUS | REDRAW_TEXT;
875 void TGHtml::RedrawText(
int y)
879 clipHeight = fCanvas->GetHeight();
881 if (y < clipHeight) {
882 RedrawArea(0, y, LARGE_NUMBER, clipHeight);
889 void TGHtml::HClear()
892 TGHtmlElement *p, *fPNext;
894 fXMargin = fYMargin = 0;
897 for (p = fPFirst; p; p = fPNext) {
904 if (fZText)
delete[] fZText;
911 for (i = 0; i < N_COLOR; ++i) {
912 if (fApColor[i] != 0) FreeColor(fApColor[i]);
919 fFgColor = AllocColor(
"black");
920 fBgColor = AllocColor(
"white");
921 fNewLinkColor = AllocColor(DEF_HTML_UNVISITED);
922 fOldLinkColor = AllocColor(DEF_HTML_VISITED);
923 fSelectionColor = AllocColor(DEF_HTML_SELECTION_COLOR);
925 fApColor[COLOR_Normal] = fFgColor;
926 fApColor[COLOR_Visited] = fOldLinkColor;
927 fApColor[COLOR_Unvisited] = fNewLinkColor;
928 fApColor[COLOR_Selection] = fSelectionColor;
929 fApColor[COLOR_Background] = fBgColor;
931 SetBackgroundColor(fApColor[COLOR_Background]->fPixel);
932 SetBackgroundPixmap(0);
937 TGHtmlImage *p2 = fImageList;
938 fImageList = p2->fPNext;
942 if (fBgImage)
delete fBgImage;
945 while (fStyleStack) {
946 SHtmlStyleStack_t *p2 = fStyleStack;
947 fStyleStack = p2->fPNext;
951 ResetLayoutContext();
955 if (fZBaseHref)
delete [] fZBaseHref;
964 fParaAlignment = ALIGN_None;
965 fRowAlignment = ALIGN_None;
973 #if 0 // in OXView::Clear()
974 fVisible = TGPosition(0, 0);
975 _virtualSize = TGDimension(0, 0);
976 ScrollTTGPosition(fVisible);
992 Bool_t TGHtml::HandleTimer(TTimer *t)
994 if (t == fInsTimer) {
995 if (fInsTimer)
delete fInsTimer;
1000 TGHtmlImage *pImage;
1001 for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
1002 if (pImage->fTimer == t) {
1003 AnimateImage(pImage);
1014 void TGHtml::FlashCursor()
1016 if (fPInsBlock == 0 || fInsOnTime <= 0 || fInsOffTime <= 0)
return;
1017 RedrawBlock(fPInsBlock);
1018 if ((fFlags & GOT_FOCUS) == 0) {
1020 }
else if (fInsStatus) {
1021 fInsTimer =
new TTimer(
this, fInsOffTime);
1024 fInsTimer =
new TTimer(
this, fInsOnTime);
1035 GContext_t TGHtml::GetGC(
int color,
int font)
1038 GcCache_t *p = fAGcCache;
1039 GCValues_t gcValues;
1044 if (color < 0 || color >= N_COLOR) color = 0;
1045 if (font < FONT_Any || font >= N_FONT) font = FONT_Default;
1047 for (i = 0; i < N_CACHE_GC; i++, p++) {
1048 if (p->fIndex == 0)
continue;
1049 if ((font < 0 || p->fFont == font) && p->fColor == color) {
1050 if (p->fIndex > 1) {
1051 for (j = 0; j < N_CACHE_GC; j++) {
1052 if (fAGcCache[j].fIndex && fAGcCache[j].fIndex < p->fIndex ) {
1053 fAGcCache[j].fIndex++;
1058 return fAGcCache[i].fGc;
1065 for (i = 0; i < N_CACHE_GC; i++, p++) {
1066 if (p->fIndex == 0 || p->fIndex == N_CACHE_GC)
break;
1068 if (i >= N_CACHE_GC) {
1070 for (i = 0; i < N_CACHE_GC && i < fGcNextToFree; ++i, ++p) {}
1071 fGcNextToFree = (fGcNextToFree + 1) % N_CACHE_GC;
1072 gVirtualX->DeleteGC(p->fGc);
1074 gcValues.fForeground = fApColor[color]->fPixel;
1075 gcValues.fGraphicsExposures = kTRUE;
1076 gcValues.fMask = kGCForeground | kGCGraphicsExposures;
1078 if (font < 0) font = FONT_Default;
1079 xfont = GetFont(font);
1082 gcValues.fFont = xfont->GetFontHandle();
1083 gcValues.fMask |= kGCFont;
1086 p->fGc = gVirtualX->CreateGC(fId, &gcValues);
1088 if (p->fIndex == 0) p->fIndex = N_CACHE_GC + 1;
1089 for (j = 0; j < N_CACHE_GC; j++) {
1090 if (fAGcCache[j].fIndex && fAGcCache[j].fIndex < p->fIndex) {
1091 fAGcCache[j].fIndex++;
1105 GContext_t TGHtml::GetAnyGC()
1108 GcCache_t *p = fAGcCache;
1110 for (i = 0; i < N_CACHE_GC; i++, p++) {
1111 if (p->fIndex)
return p->fGc;
1114 return GetGC(COLOR_Normal, FONT_Default);
1120 Bool_t TGHtml::HandleFocusChange(Event_t *event)
1122 if (event->fType == kFocusIn) {
1123 fFlags |= GOT_FOCUS | REDRAW_FOCUS;
1127 fFlags &= ~GOT_FOCUS;
1128 fFlags |= REDRAW_FOCUS;
1139 TGHtmlInput *TGHtml::GetInputElement(
int x,
int y)
1146 vw = fCanvas->GetWidth();
1147 vh = fCanvas->GetHeight();
1148 for (p = fFirstInput; p; p = p->fINext) {
1149 if (p->fFrame == 0)
continue;
1150 if (p->fY < vy + vh && p->fY + p->fH > vy &&
1151 p->fX < vx + vw && p->fX + p->fW > vx) {
1152 if ((x > p->fX) && (y > p->fY) && (x < (p->fX + p->fW)) &&
1153 (y < (p->fY + p->fH)) ) {
1164 Bool_t TGHtml::HandleHtmlInput(TGHtmlInput *pr, Event_t *event)
1168 eventSt.fType =
event->fType;
1169 eventSt.fWindow =
event->fWindow;
1170 eventSt.fTime =
event->fTime;
1173 eventSt.fXRoot =
event->fXRoot;
1174 eventSt.fYRoot =
event->fYRoot;
1175 eventSt.fCode =
event->fCode;
1176 eventSt.fState =
event->fState;
1177 eventSt.fWidth =
event->fWidth;
1178 eventSt.fHeight =
event->fHeight;
1179 eventSt.fCount =
event->fCount;
1180 eventSt.fSendEvent =
event->fSendEvent;
1181 eventSt.fHandle =
event->fHandle;
1182 eventSt.fFormat =
event->fFormat;
1183 eventSt.fUser[0] =
event->fUser[0];
1184 eventSt.fUser[1] =
event->fUser[1];
1185 eventSt.fUser[2] =
event->fUser[2];
1186 eventSt.fUser[3] =
event->fUser[3];
1187 eventSt.fUser[4] =
event->fUser[4];
1188 gVirtualX->TranslateCoordinates(GetId(), pr->fFrame->GetId(),
1189 event->fX,
event->fY, eventSt.fX,
1190 eventSt.fY, childdum);
1192 const char *name = pr->MarkupArg(
"name", 0);
1193 const char *val = pr->MarkupArg(
"value", 0);
1194 switch (pr->fItype) {
1195 case INPUT_TYPE_Submit:
1196 case INPUT_TYPE_Button: {
1197 TGButton *b = (TGButton *) pr->fFrame;
1198 Bool_t was = !b->IsDown();
1199 b->HandleButton(&eventSt);
1200 Bool_t now = !b->IsDown();
1202 if (pr->fItype == INPUT_TYPE_Submit)
1205 ButtonClicked(name, val);
1209 case INPUT_TYPE_Radio: {
1210 TGRadioButton *rb = (TGRadioButton *) pr->fFrame;
1211 Bool_t was = !rb->IsDown();
1212 rb->HandleButton(&eventSt);
1213 Bool_t now = !rb->IsDown();
1214 if ((!was && now) || (was && !now)) {
1215 HandleRadioButton(pr);
1216 RadioChanged(name, val);
1220 case INPUT_TYPE_Checkbox: {
1221 TGCheckButton *cb = (TGCheckButton *) pr->fFrame;
1222 Bool_t was = !cb->IsDown();
1223 cb->HandleButton(&eventSt);
1224 Bool_t now = !cb->IsDown();
1225 if ((!was && now) || (was && !now))
1226 CheckToggled(name, !now, val);
1229 case INPUT_TYPE_Text:
1230 case INPUT_TYPE_Password: {
1231 TGTextEntry *te = (TGTextEntry *) pr->fFrame;
1235 case INPUT_TYPE_Select: {
1236 RemoveInput(kButtonPressMask | kButtonReleaseMask | kPointerMotionMask);
1237 eventSt.fUser[0] = childdum;
1238 if (pr->fFrame->InheritsFrom(
"TGComboBox"))
1239 ((TGComboBox *)pr->fFrame)->HandleButton(&eventSt);
1240 else if (pr->fFrame->InheritsFrom(
"TGListBox"))
1241 ((TGListBox *)pr->fFrame)->HandleButton(&eventSt);
1242 InputSelected(name, val);
1243 AddInput(kButtonPressMask | kButtonReleaseMask | kPointerMotionMask);
1255 Bool_t TGHtml::HandleRadioButton(TGHtmlInput *p)
1258 for (pr = fFirstInput; pr; pr = pr->fINext) {
1259 if ((pr->fPForm == p->fPForm) && (pr->fItype == INPUT_TYPE_Radio)) {
1261 if (strcmp(pr->MarkupArg(
"name",
""), p->MarkupArg(
"name",
"")) == 0) {
1262 ((TGRadioButton *)pr->fFrame)->SetState(kButtonUp);
1274 void TGHtml::ButtonClicked(
const char *name,
const char *val)
1278 args[0] = (Long_t)name;
1279 args[1] = (Long_t)val;
1281 Emit(
"ButtonClicked(char*,char*)", args);
1287 void TGHtml::CheckToggled(
const char *name, Bool_t on,
const char *val)
1291 args[0] = (Long_t)name;
1293 args[2] = (Long_t)val;
1295 Emit(
"CheckToggled(char*,Bool_t,char*)", args);
1301 void TGHtml::RadioChanged(
const char *name,
const char *val)
1305 args[0] = (Long_t)name;
1306 args[1] = (Long_t)val;
1308 Emit(
"RadioChanged(char*,char*)", args);
1314 void TGHtml::InputSelected(
const char *name,
const char *val)
1318 args[0] = (Long_t)name;
1319 args[1] = (Long_t)val;
1321 Emit(
"InputSelected(char*,char*)", args);
1327 void TGHtml::SubmitClicked(
const char *val)
1329 Emit(
"SubmitClicked(char*)", val);
1335 Bool_t TGHtml::HandleButton(Event_t *event)
1339 ch = fCanvas->GetHeight();
1340 amount = fScrollVal.fY * TMath::Max(ch/6, 1);
1342 int ix =
event->fX + fVisible.fX;
1343 int iy =
event->fY + fVisible.fY;
1344 TGHtmlInput *pr = GetInputElement(ix, iy);
1346 HandleHtmlInput(pr, event);
1348 if ((event->fType == kButtonPress) && (event->fCode == kButton1)) {
1349 int x =
event->fX + fVisible.fX;
1350 int y =
event->fY + fVisible.fY;
1351 const char *uri = GetHref(x, y);
1353 #if 0 // insertion cursor test
1355 sprintf(ix,
"begin");
1360 uri = ResolveUri(uri);
1366 }
else if (event->fCode == kButton4) {
1367 ScrollToPosition(TGLongPosition(fVisible.fX, fVisible.fY / fScrollVal.fY - amount));
1368 }
else if (event->fCode == kButton5) {
1369 ScrollToPosition(TGLongPosition(fVisible.fX, fVisible.fY / fScrollVal.fY + amount));
1371 return TGView::HandleButton(event);
1379 Bool_t TGHtml::HandleMotion(Event_t *event)
1381 int x =
event->fX + fVisible.fX;
1382 int y =
event->fY + fVisible.fY;
1383 const char *uri = GetHref(x, y);
1386 gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
1388 gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
1391 if (uri != fLastUri) {
1393 if (uri) uri = ResolveUri(uri);
1406 TGFont *TGHtml::GetFont(
int iFont)
1410 if (iFont < 0) iFont = 0;
1411 if (iFont >= N_FONT) { iFont = N_FONT - 1; CANT_HAPPEN; }
1418 if (!FontIsValid(iFont) && fAFont[iFont] != 0) {
1419 toFree = fAFont[iFont];
1426 if (fAFont[iFont] == 0) {
1428 const char *familyStr =
"";
1433 iFamily = FontFamily(iFont) >> 3;
1434 iSize = FontSize(iFont) + 1;
1439 case 0: familyStr =
"times -%d";
break;
1440 case 1: familyStr =
"times -%d bold";
break;
1441 case 2: familyStr =
"times -%d italic";
break;
1442 case 3: familyStr =
"times -%d bold italic";
break;
1443 case 4: familyStr =
"courier -%d";
break;
1444 case 5: familyStr =
"courier -%d bold";
break;
1445 case 6: familyStr =
"courier -%d italic";
break;
1446 case 7: familyStr =
"courier -%d bold italic";
break;
1447 default: familyStr =
"times -16"; CANT_HAPPEN;
1449 case 0: familyStr =
"helvetica -%d";
break;
1450 case 1: familyStr =
"helvetica -%d bold";
break;
1451 case 2: familyStr =
"helvetica -%d italic";
break;
1452 case 3: familyStr =
"helvetica -%d bold italic";
break;
1453 case 4: familyStr =
"courier -%d";
break;
1454 case 5: familyStr =
"courier -%d bold";
break;
1455 case 6: familyStr =
"courier -%d italic";
break;
1456 case 7: familyStr =
"courier -%d bold italic";
break;
1457 default: familyStr =
"helvetica -14"; CANT_HAPPEN;
1462 case 1: size = 6+finc;
break;
1463 case 2: size = 10+finc;
break;
1464 case 3: size = 12+finc;
break;
1465 case 4: size = 14+finc;
break;
1466 case 5: size = 20+finc;
break;
1467 case 6: size = 24+finc;
break;
1468 case 7: size = 30+finc;
break;
1469 default: size = 14+finc; CANT_HAPPEN;
1473 case 1: size = 8;
break;
1474 case 2: size = 10;
break;
1475 case 3: size = 12;
break;
1476 case 4: size = 14;
break;
1477 case 5: size = 16;
break;
1478 case 6: size = 18;
break;
1479 case 7: size = 24;
break;
1480 default: size = 14; CANT_HAPPEN;
1484 if (iFamily < 4) size += 2;
1487 snprintf(name, 199, familyStr, size);
1490 fAFont[iFont] = fClient->GetFont(name);
1492 if (fAFont[iFont] == 0) {
1493 fprintf(stderr,
"TGHtml: could not get font \"%s\", trying fixed\n",
1495 fAFont[iFont] = fClient->GetFont(
"fixed");
1497 if (fAFont[iFont] == 0 ){
1498 fprintf(stderr,
"TGHtml: could not get font \"fixed\", trying "
1499 "\"helvetica -12\"\n");
1500 fAFont[iFont] = fClient->GetFont(
"helvetica -12");
1502 FontSetValid(iFont);
1507 if (toFree) fClient->FreeFont(toFree);
1509 return fAFont[iFont];
1515 int TGHtml::InArea(TGHtmlMapArea *p,
int left,
int top,
int x,
int y)
1517 int *ip = p->fCoords;
1520 if (p->fMType == HTML_MAP_RECT) {
1521 return ((left + ip[0]) <= x && (left + ip[2]) >= x &&
1522 (top + ip[1]) <= y && (top + ip[3]) >= y);
1523 }
else if (p->fMType == HTML_MAP_CIRCLE) {
1524 int dx = left + ip[0] - x;
1525 int dy = top + ip[1] - y;
1526 return (dx * dx + dy * dy <= ip[2] * ip[2]);
1534 TGHtmlElement *TGHtml::GetMap(
const char *name)
1536 TGHtmlElement *p = fPFirst;
1540 if (p->fType == Html_MAP) {
1541 z = p->MarkupArg(
"name", 0);
1542 zb = p->MarkupArg(
"shape", 0);
1543 if (zb && *zb !=
'r')
return 0;
1544 if (z && !strcmp(z, name))
return p;
1554 float TGHtml::ColorDistance(ColorStruct_t *pA, ColorStruct_t *pB)
1558 x = 0.30 * (pA->fRed - pB->fRed);
1559 y = 0.61 * (pA->fGreen - pB->fGreen);
1560 z = 0.11 * (pA->fBlue - pB->fBlue);
1562 return x*x + y*y + z*z;
1570 int TGHtml::GetColorByName(
const char *zColor)
1572 ColorStruct_t *pNew;
1583 if (n == 6 || n == 3 || n == 9 || n == 12) {
1584 for (i = 0; i < n; i++) {
1585 if (!isxdigit(zColor[i]))
break;
1588 snprintf(zAltColor, 15,
"#%s", zColor);
1590 strlcpy(zAltColor, zColor,
sizeof(zAltColor));
1592 name = GetUid(zAltColor);
1594 name = GetUid(zColor);
1597 pNew = AllocColor(name);
1602 iColor = GetColorByValue(pNew);
1611 #define MAX_COLOR 65535
1612 #define MAX(A,B) ((A)<(B)?(B):(A))
1613 #define MIN(A,B) ((A)<(B)?(A):(B))
1619 int TGHtml::IsDarkColor(ColorStruct_t *p)
1624 y = 1.00 * p->fGreen;
1625 z = 0.28 * p->fBlue;
1626 return (x*x + y*y + z*z) < (0.05 * MAX_COLOR * MAX_COLOR);
1633 int TGHtml::GetDarkShadowColor(
int iBgColor)
1635 if (fIDark[iBgColor] == 0) {
1636 ColorStruct_t *pRef, val;
1637 val.fMask = kDoRed | kDoGreen | kDoBlue;
1639 pRef = fApColor[iBgColor];
1640 if (IsDarkColor(pRef)) {
1642 t1 = (int) MIN(MAX_COLOR, pRef->fRed * 1.2);
1643 t2 = (pRef->fRed * 3 + MAX_COLOR) / 4;
1644 val.fRed = MAX(t1, t2);
1645 t1 = (int) MIN(MAX_COLOR, pRef->fGreen * 1.2);
1646 t2 = (pRef->fGreen * 3 + MAX_COLOR) / 4;
1647 val.fGreen = MAX(t1, t2);
1648 t1 = (int) MIN(MAX_COLOR, pRef->fBlue * 1.2);
1649 t2 = (pRef->fBlue * 3 + MAX_COLOR) / 4;
1650 val.fBlue = MAX(t1, t2);
1652 val.fRed = (
unsigned short) (pRef->fRed * 0.6);
1653 val.fGreen = (
unsigned short) (pRef->fGreen * 0.6);
1654 val.fBlue = (
unsigned short) (pRef->fBlue * 0.6);
1656 fIDark[iBgColor] = GetColorByValue(&val) + 1;
1659 return fIDark[iBgColor] - 1;
1666 int TGHtml::IsLightColor(ColorStruct_t *p)
1668 return p->fGreen >= 0.85 * MAX_COLOR;
1675 int TGHtml::GetLightShadowColor(
int iBgColor)
1677 if (fILight[iBgColor] == 0) {
1678 ColorStruct_t *pRef, val;
1679 val.fMask = kDoRed | kDoGreen | kDoBlue;
1681 pRef = fApColor[iBgColor];
1682 if (IsLightColor(pRef)) {
1683 val.fRed = (
unsigned short) (pRef->fRed * 0.9);
1684 val.fGreen = (
unsigned short) (pRef->fGreen * 0.9);
1685 val.fBlue = (
unsigned short) (pRef->fBlue * 0.9);
1688 t1 = (int) MIN(MAX_COLOR, pRef->fGreen * 1.4);
1689 t2 = (pRef->fGreen + MAX_COLOR) / 2;
1690 val.fGreen = MAX(t1, t2);
1691 t1 = (int) MIN(MAX_COLOR, pRef->fRed * 1.4);
1692 t2 = (pRef->fRed + MAX_COLOR) / 2;
1693 val.fRed = MAX(t1, t2);
1694 t1 = (int) MIN(MAX_COLOR, pRef->fBlue * 1.4);
1695 t2 = (pRef->fBlue + MAX_COLOR) / 2;
1696 val.fBlue = MAX(t1, t2);
1698 fILight[iBgColor] = GetColorByValue(&val) + 1;
1701 return fILight[iBgColor] - 1;
1708 int TGHtml::GetColorByValue(ColorStruct_t *pRef)
1715 # define COLOR_MASK 0xf800
1718 r = pRef->fRed & COLOR_MASK;
1719 g = pRef->fGreen & COLOR_MASK;
1720 b = pRef->fBlue & COLOR_MASK;
1721 for (i = 0; i < N_COLOR; i++) {
1722 ColorStruct_t *p = fApColor[i];
1724 ((p->fRed & COLOR_MASK) == r) &&
1725 ((p->fGreen & COLOR_MASK) == g) &&
1726 ((p->fBlue & COLOR_MASK) == b)) {
1727 fColorUsed |= (1<<i);
1733 for (i = N_PREDEFINED_COLOR; i < N_COLOR; i++) {
1734 if (fApColor[i] == 0) {
1735 fApColor[i] = AllocColorByValue(pRef);
1736 fColorUsed |= (1<<i);
1743 for (i = N_PREDEFINED_COLOR; i < N_COLOR; i++) {
1744 if (((fColorUsed >> i) & 1) == 0) {
1745 FreeColor(fApColor[i]);
1746 fApColor[i] = AllocColorByValue(pRef);
1747 fColorUsed |= (1<<i);
1755 closestDist = ColorDistance(pRef, fApColor[0]);
1756 for (i = 1; i < N_COLOR; i++) {
1757 dist = ColorDistance(pRef, fApColor[i]);
1758 if (dist < closestDist) {
1772 const char *TGHtml::GetHref(
int x,
int y,
const char **target)
1774 TGHtmlBlock *pBlock;
1775 TGHtmlElement *pElem;
1777 for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
1778 if (pBlock->fTop > y || pBlock->fBottom < y ||
1779 pBlock->fLeft > x || pBlock->fRight < x)
continue;
1780 pElem = pBlock->fPNext;
1781 if (pElem->fType == Html_IMG) {
1782 TGHtmlImageMarkup *image = (TGHtmlImageMarkup *) pElem;
1784 pElem = image->fPMap->fPNext;
1785 while (pElem && pElem->fType != Html_EndMAP) {
1786 if (pElem->fType == Html_AREA) {
1787 if (InArea((TGHtmlMapArea *) pElem, pBlock->fLeft, pBlock->fTop, x, y)) {
1788 if (target) *target = pElem->MarkupArg(
"target", 0);
1789 return pElem->MarkupArg(
"href", 0);
1792 pElem = pElem->fPNext;
1797 if ((pElem->fStyle.fFlags & STY_Anchor) == 0)
continue;
1798 switch (pElem->fType) {
1802 while (pElem && pElem->fType != Html_A) pElem = pElem->fPPrev;
1803 if (pElem == 0 || pElem->fType != Html_A)
break;
1804 if (target) *target = pElem->MarkupArg(
"target", 0);
1805 return pElem->MarkupArg(
"href", 0);
1818 int TGHtml::ElementCoords(TGHtmlElement *p,
int ,
int pct,
int *coords)
1820 TGHtmlBlock *pBlock;
1822 while (p && p->fType != Html_Block) p = p->fPPrev;
1825 pBlock = (TGHtmlBlock *) p;
1827 TGHtmlElement *pEnd = fPLast;
1829 while (pEnd && pEnd->fType != Html_Block) pEnd = pEnd->fPPrev;
1830 pb2 = (TGHtmlBlock *) pEnd;
1831 #define HGCo(dir) (pb2 && pb2->dir) ? pBlock->dir * 100 / pb2->dir : 0
1832 coords[0] = HGCo(fLeft);
1833 coords[1] = HGCo(fTop);
1834 coords[3] = HGCo(fRight);
1835 coords[4] = HGCo(fBottom);
1837 coords[0] = pBlock->fLeft;
1838 coords[1] = pBlock->fTop;
1839 coords[2] = pBlock->fRight;
1840 coords[3] = pBlock->fBottom;
1848 TGHtmlElement *TGHtml::AttrElem(
const char *name,
char *value)
1853 for (p = fPFirst; p; p = p->fPNext) {
1854 if (p->fType != Html_A)
continue;
1855 z = p->MarkupArg(name, 0);
1856 if (z && (strcmp(z, value) == 0))
return p;
1869 void TGHtml::UpdateSelection(
int forceUpdate)
1871 TGHtmlBlock *pBlock;
1873 int needUpdate = forceUpdate;
1876 if (fSelEnd.fP == 0) fSelBegin.fP = 0;
1878 IndexToBlockIndex(fSelBegin, &pBlock, &index);
1879 if (needUpdate || pBlock != fPSelStartBlock) {
1881 RedrawBlock(fPSelStartBlock);
1882 fPSelStartBlock = pBlock;
1883 fSelStartIndex = index;
1884 }
else if (index != fSelStartIndex) {
1885 RedrawBlock(pBlock);
1886 fSelStartIndex = index;
1889 if (fSelBegin.fP == 0) fSelEnd.fP = 0;
1891 IndexToBlockIndex(fSelEnd, &pBlock, &index);
1892 if (needUpdate || pBlock != fPSelEndBlock) {
1894 RedrawBlock(fPSelEndBlock);
1895 fPSelEndBlock = pBlock;
1896 fSelEndIndex = index;
1897 }
else if (index != fSelEndIndex) {
1898 RedrawBlock(pBlock);
1899 fSelEndIndex = index;
1902 if (fPSelStartBlock && fPSelStartBlock == fPSelEndBlock &&
1903 fSelStartIndex > fSelEndIndex) {
1904 temp = fSelStartIndex;
1905 fSelStartIndex = fSelEndIndex;
1906 fSelEndIndex = temp;
1910 fFlags |= ANIMATE_IMAGES;
1911 UpdateSelectionDisplay();
1922 void TGHtml::UpdateSelectionDisplay()
1925 SHtmlIndex_t tempIndex;
1926 TGHtmlBlock *pTempBlock;
1930 for (p = fFirstBlock; p; p = p->fBNext) {
1931 if (p == fPSelStartBlock) {
1934 }
else if (!selected && p == fPSelEndBlock) {
1936 tempIndex = fSelBegin;
1937 fSelBegin = fSelEnd;
1938 fSelEnd = tempIndex;
1939 pTempBlock = fPSelStartBlock;
1940 fPSelStartBlock = fPSelEndBlock;
1941 fPSelEndBlock = pTempBlock;
1942 temp = fSelStartIndex;
1943 fSelStartIndex = fSelEndIndex;
1944 fSelEndIndex = temp;
1947 if (p->fFlags & HTML_Selected) {
1949 p->fFlags &= ~HTML_Selected;
1954 p->fFlags |= HTML_Selected;
1958 if (p == fPSelEndBlock) {
1968 void TGHtml::LostSelection()
1970 if (fExportSelection) {
1972 fPSelStartBlock = 0;
1976 UpdateSelectionDisplay();
1983 int TGHtml::SelectionSet(
const char *startIx,
const char *endIx)
1985 SHtmlIndex_t sBegin, sEnd;
1988 if (GetIndex(startIx, &sBegin.fP, &sBegin.fI)) {
1993 if (GetIndex(endIx, &sEnd.fP, &sEnd.fI)) {
1998 bi = TokenNumber(sBegin.fP);
1999 ei = TokenNumber(sEnd.fP);
2001 if (!(sBegin.fP && sEnd.fP))
return kTRUE;
2003 if (bi < ei || (bi == ei && sBegin.fI <= sEnd.fI)) {
2012 if (fExportSelection) {
2025 void TGHtml::UpdateInsert()
2027 IndexToBlockIndex(fIns, &fPInsBlock, &fInsIndex);
2028 RedrawBlock(fPInsBlock);
2029 if (fInsTimer == 0) {
2038 int TGHtml::SetInsert(
const char *insIx)
2043 RedrawBlock(fPInsBlock);
2048 if (GetIndex(insIx, &i.fP, &i.fI)) {
2052 RedrawBlock(fPInsBlock);
2063 void TGHtml::SavePrimitive(std::ostream &out, Option_t *option )
2066 out << GetName() <<
" = new TGHtml(" << fParent->GetName()
2067 <<
"," << GetWidth() <<
"," << GetHeight()
2068 <<
");"<< std::endl;
2069 if (option && strstr(option,
"keep_names"))
2070 out <<
" " << GetName() <<
"->SetName(\"" << GetName() <<
"\");" << std::endl;
2072 if (fCanvas->GetBackground() != TGFrame::GetWhitePixel()) {
2073 out <<
" " << GetName() <<
"->ChangeBackground(" << fCanvas->GetBackground() <<
");" << std::endl;
2077 TGText txt(GetText());
2078 fn.Form(
"Html%s.htm", GetName()+5);
2079 txt.Save(fn.Data());
2080 out <<
" " <<
"FILE *f = fopen(\"" << fn.Data() <<
"\", \"r\");" << std::endl;
2081 out <<
" " <<
"if (f) {" << std::endl;
2082 out <<
" " << GetName() <<
"->Clear();" << std::endl;
2083 out <<
" " << GetName() <<
"->Layout();" << std::endl;
2084 out <<
" " << GetName() <<
"->SetBaseUri(\"\");" << std::endl;
2085 out <<
" " <<
"char *buf = (char *)calloc(4096, sizeof(char));" << std::endl;
2086 out <<
" " <<
"while (fgets(buf, 4096, f)) {" << std::endl;
2087 out <<
" " << GetName() <<
"->ParseText(buf);" << std::endl;
2088 out <<
" " <<
"}" << std::endl;
2089 out <<
" " <<
"free(buf);" << std::endl;
2090 out <<
" " <<
"fclose(f);" << std::endl;
2091 out <<
" " <<
"}" << std::endl;
2092 out <<
" " << GetName() <<
"->Layout();" << std::endl;