49 ClassImp(TGHtmlBrowser);
51 enum EMyMessageTypes {
61 static const char *gHtmlFTypes[] = {
62 "HTML files",
"*.htm*",
67 const char *HtmlError[] = {
68 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd\"> ",
69 "<HTML><HEAD><TITLE>RHTML cannot display the webpage</TITLE> ",
70 "<META http-equiv=Content-Type content=\"text/html; charset=UTF-8\"></HEAD> ",
72 "<TABLE cellSpacing=0 cellPadding=0 width=730 border=0> ",
75 " <TD id=infoIconAlign vAlign=top align=left width=60 rowSpan=2> ",
76 " <IMG src=\"info.gif\"> ",
78 " <TD id=mainTitleAlign vAlign=center align=left width=*> ",
79 " <H1 id=mainTitle>RHTML cannot display the webpage</H1></TD></TR> ",
81 " <TD class=errorCodeAndDivider id=errorCodeAlign align=right> ",
82 " <DIV class=divider></DIV></TD></TR> ",
87 " <TD id=MostLikelyAlign vAlign=top align=left> ",
88 " <H3 id=likelyCauses>Most likely causes:</H3> ",
90 " <LI id=causeNotConnected>You are not connected to the Internet. ",
91 " <LI id=causeSiteProblem>The website is encountering problems. ",
92 " <LI id=causeErrorInAddress>There might be a typing error in the address. ",
93 " <LI id=causeOtherError> ",
94 " </LI></UL></TD></TR> ",
96 " <TD id=infoBlockAlign vAlign=top align=right> </TD> ",
97 " <TD id=moreInformationAlign vAlign=center align=left> ",
102 " <TD vAlign=top><SPAN id=moreInfoContainer></SPAN><ID ",
103 " id=moreInformation>More information</ID> ",
104 " </TD></TR></TBODY></TABLE></H4> ",
105 " <DIV class=infoBlock id=infoBlockID> ",
106 " <P><ID id=errorExpl1>This problem can be caused by a variety of issues, ",
109 " <LI id=errorExpl2>Internet connectivity has been lost. ",
110 " <LI id=errorExpl3>The website is temporarily unavailable. ",
111 " <LI id=errorExpl4>The Domain Name Server (DNS) is not reachable. ",
112 " <LI id=errorExpl5>The Domain Name Server (DNS) does not have a listing ",
113 " for the website's domain. ",
115 " <P></P></DIV></TD></TR></TBODY></TABLE></BODY></HTML> ",
122 TGHtmlBrowser::TGHtmlBrowser(
const char *filename,
const TGWindow *p, UInt_t w, UInt_t h)
123 : TGMainFrame(p, w, h)
125 SetCleanup(kDeepCleanup);
127 fMenuBar =
new TGMenuBar(
this, 35, 50, kHorizontalFrame);
129 fMenuFile =
new TGPopupMenu(gClient->GetDefaultRoot());
130 fMenuFile->AddEntry(
" &Open...\tCtrl+O", kM_FILE_OPEN, 0,
131 gClient->GetPicture(
"ed_open.png"));
132 fMenuFile->AddEntry(
" Save &As...\tCtrl+A", kM_FILE_SAVEAS, 0,
133 gClient->GetPicture(
"ed_save.png"));
134 fMenuFile->AddEntry(
" &Browse...\tCtrl+B", kM_FILE_BROWSE);
135 fMenuFile->AddSeparator();
136 fMenuFile->AddEntry(
" E&xit\tCtrl+Q", kM_FILE_EXIT, 0,
137 gClient->GetPicture(
"bld_exit.png"));
138 fMenuFile->Associate(
this);
140 fMenuFavorites =
new TGPopupMenu(gClient->GetDefaultRoot());
141 fMenuFavorites->AddEntry(
"&Add to Favorites", kM_FAVORITES_ADD, 0,
142 gClient->GetPicture(
"bld_plus.png"));
143 fMenuFavorites->AddSeparator();
144 fMenuFavorites->AddEntry(
"http://root.cern.ch", fNbFavorites++, 0,
145 gClient->GetPicture(
"htmlfile.gif"));
146 fMenuFavorites->Associate(
this);
148 fMenuTools =
new TGPopupMenu(gClient->GetDefaultRoot());
149 fMenuTools->AddEntry(
"&Clear History", kM_TOOLS_CLEARHIST, 0,
150 gClient->GetPicture(
"ed_delete.png"));
151 fMenuTools->Associate(
this);
153 fMenuHelp =
new TGPopupMenu(gClient->GetDefaultRoot());
154 fMenuHelp->AddEntry(
" &About...", kM_HELP_ABOUT, 0, gClient->GetPicture(
"about.xpm"));
155 fMenuHelp->Associate(
this);
157 fMenuBar->AddPopup(
"&File", fMenuFile,
new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0));
158 fMenuBar->AddPopup(
"&Favorites", fMenuFavorites,
new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0));
159 fMenuBar->AddPopup(
"&Tools", fMenuTools,
new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0));
160 fMenuBar->AddPopup(
"&Help", fMenuHelp,
new TGLayoutHints(kLHintsTop | kLHintsRight));
162 AddFrame(fMenuBar,
new TGLayoutHints(kLHintsTop | kLHintsExpandX));
165 fVerticalFrame =
new TGVerticalFrame(
this,727,600,kVerticalFrame);
167 fHorizontalFrame =
new TGHorizontalFrame(fVerticalFrame,727,600);
169 fBack =
new TGPictureButton(fHorizontalFrame,gClient->GetPicture(
"GoBack.gif"));
170 fBack->SetStyle(gClient->GetStyle());
171 fBack->SetToolTipText(
"Go Back");
172 fHorizontalFrame->AddFrame(fBack,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsCenterY,2,2,2,2));
173 fBack->Connect(
"Clicked()",
"TGHtmlBrowser",
this,
"Back()");
175 fForward =
new TGPictureButton(fHorizontalFrame,gClient->GetPicture(
"GoForward.gif"));
176 fForward->SetStyle(gClient->GetStyle());
177 fForward->SetToolTipText(
"Go Forward");
178 fHorizontalFrame->AddFrame(fForward,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsCenterY,2,2,2,2));
179 fForward->Connect(
"Clicked()",
"TGHtmlBrowser",
this,
"Forward()");
181 fReload =
new TGPictureButton(fHorizontalFrame,gClient->GetPicture(
"ReloadPage.gif"));
182 fReload->SetStyle(gClient->GetStyle());
183 fReload->SetToolTipText(
"Reload Page");
184 fHorizontalFrame->AddFrame(fReload,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsCenterY,2,2,2,2));
185 fReload->Connect(
"Clicked()",
"TGHtmlBrowser",
this,
"Reload()");
187 fStop =
new TGPictureButton(fHorizontalFrame,gClient->GetPicture(
"StopLoading.gif"));
188 fStop->SetStyle(gClient->GetStyle());
189 fStop->SetToolTipText(
"Stop Loading");
190 fHorizontalFrame->AddFrame(fStop,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsCenterY,2,2,2,2));
191 fStop->Connect(
"Clicked()",
"TGHtmlBrowser",
this,
"Stop()");
193 fHome =
new TGPictureButton(fHorizontalFrame,gClient->GetPicture(
"GoHome.gif"));
194 fHome->SetStyle(gClient->GetStyle());
195 fHome->SetToolTipText(
"Go to ROOT HomePage\n (http://root.cern.ch)");
196 fHorizontalFrame->AddFrame(fHome,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsCenterY,2,2,2,2));
197 fHome->Connect(
"Clicked()",
"TGHtmlBrowser",
this,
"Selected(=\"http://root.cern.ch\")");
200 fURLBuf =
new TGTextBuffer(256);
201 fComboBox =
new TGComboBox(fHorizontalFrame,
"");
202 fURL = fComboBox->GetTextEntry();
203 fURLBuf = fURL->GetBuffer();
204 fComboBox->Resize(200, fURL->GetDefaultHeight());
205 fURL->Connect(
"ReturnPressed()",
"TGHtmlBrowser",
this,
"URLChanged()");
208 fComboBox->AddEntry(filename, 1);
209 fURL->SetText(filename);
211 fComboBox->Select(0);
212 fComboBox->Connect(
"Selected(char *)",
"TGHtmlBrowser",
this,
"Selected(char *)");
214 fHorizontalFrame->AddFrame(fComboBox,
new TGLayoutHints(kLHintsLeft | kLHintsCenterY | kLHintsExpandX,2,2,2,2));
216 fVerticalFrame->AddFrame(fHorizontalFrame,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
219 fHtml =
new TGHtml(fVerticalFrame, 10, 10, -1);
220 fVerticalFrame->AddFrame(fHtml,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX | kLHintsExpandY,2,2,2,2));
222 AddFrame(fVerticalFrame,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX | kLHintsExpandY,2,2,2,2));
225 fStatusBar =
new TGStatusBar(
this,100,20);
226 Int_t partsusBar[] = {75,25};
227 fStatusBar->SetParts(partsusBar,2);
228 AddFrame(fStatusBar,
new TGLayoutHints(kLHintsBottom | kLHintsExpandX));
230 fHtml->Connect(
"MouseOver(const char *)",
"TGHtmlBrowser",
this,
"MouseOver(const char *)");
231 fHtml->Connect(
"MouseDown(const char *)",
"TGHtmlBrowser",
this,
"MouseDown(const char *)");
234 Resize(GetDefaultSize());
245 Ssiz_t ReadSize(
const char *url)
251 TString msg =
"HEAD ";
252 msg += fUrl.GetProtocol();
254 msg += fUrl.GetHost();
256 msg += fUrl.GetPort();
258 msg += fUrl.GetFile();
261 msg +=
"User-Agent: ROOT-TWebFile/1.1";
266 if (!uri.BeginsWith(
"http://") && !uri.BeginsWith(
"https://"))
268 if (uri.BeginsWith(
"https://")) {
270 s =
new TSSLSocket(fUrl.GetHost(), fUrl.GetPort());
272 ::Error(
"ReadSize",
"library compiled without SSL, https not supported");
277 s =
new TSocket(fUrl.GetHost(), fUrl.GetPort());
283 if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
287 if (s->RecvRaw(buf, 4096) == -1) {
292 Ssiz_t idx = reply.Index(
"Content-length:", 0, TString::kIgnoreCase);
295 TString slen = reply(idx, reply.Length() - idx);
297 return (Ssiz_t)atol(slen.Data());
306 static char *ReadRemote(
const char *url)
308 static char *buf = 0;
311 Ssiz_t size = ReadSize(url);
312 if (size <= 0) size = 1024*1024;
314 TString msg =
"GET ";
315 msg += fUrl.GetProtocol();
317 msg += fUrl.GetHost();
319 msg += fUrl.GetPort();
321 msg += fUrl.GetFile();
326 if (!uri.BeginsWith(
"http://") && !uri.BeginsWith(
"https://"))
328 if (uri.BeginsWith(
"https://")) {
330 s =
new TSSLSocket(fUrl.GetHost(), fUrl.GetPort());
332 ::Error(
"ReadRemote",
"library compiled without SSL, https not supported");
337 s =
new TSocket(fUrl.GetHost(), fUrl.GetPort());
343 if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
347 buf = (
char *)calloc(size+1,
sizeof(
char));
348 if (s->RecvRaw(buf, size) == -1) {
360 void TGHtmlBrowser::Selected(
const char *uri)
365 if (CheckAnchors(uri))
368 TString surl(gSystem->UnixPathName(uri));
369 if (!surl.BeginsWith(
"http://") && !surl.BeginsWith(
"https://") &&
370 !surl.BeginsWith(
"ftp://") && !surl.BeginsWith(
"file://")) {
371 if (surl.BeginsWith(
"file:"))
372 surl.ReplaceAll(
"file:",
"file://");
374 surl.Prepend(
"file://");
376 if (surl.EndsWith(
".root")) {
378 gVirtualX->SetCursor(fHtml->GetId(), gVirtualX->CreateCursor(kWatch));
379 gROOT->ProcessLine(Form(
"TFile::Open(\"%s\");", surl.Data()));
380 Clicked((
char *)surl.Data());
381 gROOT->RefreshBrowsers();
382 gVirtualX->SetCursor(fHtml->GetId(), gVirtualX->CreateCursor(kPointer));
385 gVirtualX->SetCursor(fHtml->GetId(), gVirtualX->CreateCursor(kWatch));
386 TUrl url(surl.Data());
387 if (surl.EndsWith(
".pdf", TString::kIgnoreCase)) {
390 if (!gVirtualX->InheritsFrom(
"TGX11")) {
391 TString cmd = TString::Format(
"explorer %s", surl.Data());
392 gSystem->Exec(cmd.Data());
394 gVirtualX->SetCursor(fHtml->GetId(), gVirtualX->CreateCursor(kPointer));
397 if (surl.EndsWith(
".gif") || surl.EndsWith(
".jpg") || surl.EndsWith(
".png")) {
401 snprintf(imgHtml, 1000,
"<IMG src=\"%s\"> ", surl.Data());
402 fHtml->ParseText(imgHtml);
403 fHtml->SetBaseUri(url.GetUrl());
404 fURL->SetText(surl.Data());
405 if (!fComboBox->FindEntry(surl.Data()))
406 fComboBox->AddEntry(surl.Data(), fComboBox->GetNumberOfEntries()+1);
408 gVirtualX->SetCursor(fHtml->GetId(), gVirtualX->CreateCursor(kPointer));
411 if (!strcmp(url.GetProtocol(),
"http") ||
412 !strcmp(url.GetProtocol(),
"https")) {
414 buf = ReadRemote(url.GetUrl());
418 fHtml->SetBaseUri(url.GetUrl());
419 fHtml->ParseText(buf);
421 fURL->SetText(surl.Data());
422 if (!fComboBox->FindEntry(surl.Data()))
423 fComboBox->AddEntry(surl.Data(), fComboBox->GetNumberOfEntries()+1);
428 fHtml->SetBaseUri(
"");
429 for (
int i=0; HtmlError[i]; i++) {
430 fHtml->ParseText((
char *)HtmlError[i]);
436 f = fopen(url.GetFile(),
"r");
438 TString fpath = url.GetUrl();
439 fpath.ReplaceAll(gSystem->BaseName(fpath.Data()),
"");
440 fpath.ReplaceAll(
"file://",
"");
443 fHtml->SetBaseUri(fpath.Data());
444 buf = (
char *)calloc(4096,
sizeof(
char));
446 while (fgets(buf, 4096, f)) {
447 fHtml->ParseText(buf);
452 fURL->SetText(surl.Data());
453 if (!fComboBox->FindEntry(surl.Data()))
454 fComboBox->AddEntry(surl.Data(), fComboBox->GetNumberOfEntries()+1);
459 fHtml->SetBaseUri(
"");
460 for (
int i=0; HtmlError[i]; i++) {
461 fHtml->ParseText((
char *)HtmlError[i]);
466 gVirtualX->SetCursor(fHtml->GetId(), gVirtualX->CreateCursor(kPointer));
468 Ssiz_t idx = surl.Last(
'#');
471 TString anchor = surl(idx, surl.Length() - idx);
472 fHtml->GotoAnchor(anchor.Data());
474 SetWindowName(Form(
"%s - RHTML",surl.Data()));
480 void TGHtmlBrowser::URLChanged()
482 const char *
string = fURL->GetText();
484 Selected(gSystem->UnixPathName(
string));
491 void TGHtmlBrowser::Back()
494 const char *
string = fURL->GetText();
495 TGLBEntry * lbe1 = fComboBox->FindEntry(
string);
497 index = lbe1->EntryId();
499 fComboBox->Select(index - 1, kTRUE);
500 TGTextLBEntry *entry = (TGTextLBEntry *)fComboBox->GetSelectedEntry();
502 string = entry->GetTitle();
513 Bool_t TGHtmlBrowser::CheckAnchors(
const char *uri)
515 TString surl(gSystem->UnixPathName(uri));
517 if (!fHtml->GetBaseUri())
519 TString actual = fHtml->GetBaseUri();
520 Ssiz_t idx = surl.Last(
'#');
521 Ssiz_t idy = actual.Last(
'#');
522 TString short1(surl.Data());
523 TString short2(actual.Data());
525 short1 = surl(0, idx);
527 short2 = actual(0, idy);
529 if (short1 == short2) {
532 TString anchor = surl(idx, surl.Length() - idx);
533 fHtml->GotoAnchor(anchor.Data());
536 fHtml->ScrollToPosition(TGLongPosition(0, 0));
538 fHtml->SetBaseUri(surl.Data());
539 if (!fComboBox->FindEntry(surl.Data()))
540 fComboBox->AddEntry(surl.Data(), fComboBox->GetNumberOfEntries()+1);
541 fURL->SetText(surl.Data());
542 fComboBox->Select(fComboBox->GetNumberOfEntries(), kFALSE);
543 SetWindowName(Form(
"%s - RHTML",surl.Data()));
552 void TGHtmlBrowser::Forward()
555 const char *
string = fURL->GetText();
556 TGLBEntry * lbe1 = fComboBox->FindEntry(
string);
558 index = lbe1->EntryId();
559 if (index < fComboBox->GetNumberOfEntries()) {
560 fComboBox->Select(index + 1, kTRUE);
561 TGTextLBEntry *entry = (TGTextLBEntry *)fComboBox->GetSelectedEntry();
563 string = entry->GetTitle();
573 void TGHtmlBrowser::Reload()
575 const char *
string = fURL->GetText();
583 void TGHtmlBrowser::Stop()
590 void TGHtmlBrowser::MouseOver(
const char *url)
592 fStatusBar->SetText(url, 0);
598 void TGHtmlBrowser::MouseDown(
const char *url)
606 Bool_t TGHtmlBrowser::ProcessMessage(Long_t msg, Long_t parm1, Long_t)
608 switch (GET_MSG(msg)) {
611 switch (GET_SUBMSG(msg)) {
624 static TString dir(
".");
626 fi.fFileTypes = gHtmlFTypes;
627 fi.fIniDir = StrDup(dir);
628 new TGFileDialog(fClient->GetRoot(),
this,
632 Selected(Form(
"file://%s",
633 gSystem->UnixPathName(fi.fFilename)));
640 static TString sdir(
".");
642 fi.fFileTypes = gHtmlFTypes;
643 fi.fIniDir = StrDup(sdir);
644 new TGFileDialog(fClient->GetRoot(),
this,
648 TGText txt(fHtml->GetText());
649 txt.Save(gSystem->UnixPathName(fi.fFilename));
654 case kM_FAVORITES_ADD:
655 fMenuFavorites->AddEntry(Form(
"%s",
656 fURL->GetText()), fNbFavorites++, 0,
657 gClient->GetPicture(
"htmlfile.gif"));
660 case kM_TOOLS_CLEARHIST:
661 fComboBox->RemoveEntries(1,fComboBox->GetNumberOfEntries());
671 TString rootx = TROOT::GetBinDir() +
"/root -a &";
672 gSystem->Exec(rootx);
675 new TWin32SplashThread(kTRUE);
678 snprintf(str, 32,
"About ROOT %s...", gROOT->GetVersion());
679 TRootHelpDialog *hd =
new TRootHelpDialog(
this, str,
681 hd->SetText(gHelpAbout);
690 if (parm1 < 1000)
break;
691 TGMenuEntry *entry = fMenuFavorites->GetEntry(parm1);
693 const char *shortcut = entry->GetName();