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
00035
00036 #include <string.h>
00037 #include <stdlib.h>
00038
00039 #include "TGHtml.h"
00040
00041 #include "TImage.h"
00042 #include "TUrl.h"
00043 #include "TSocket.h"
00044 #include "TSystem.h"
00045
00046
00047 TGHtmlImage::TGHtmlImage(TGHtml *htm, const char *url, const char *width,
00048 const char *height)
00049 {
00050
00051
00052 fHtml = htm;
00053 fZUrl = StrDup(url);
00054 fZWidth = StrDup(width);
00055 fZHeight = StrDup(height);
00056 fImage = NULL;
00057 fPNext = NULL;
00058 fPList = NULL;
00059 fW = 0;
00060 fH = 0;
00061 fTimer = NULL;
00062 }
00063
00064
00065 TGHtmlImage::~TGHtmlImage()
00066 {
00067
00068
00069 delete [] fZUrl;
00070 delete [] fZWidth;
00071 delete [] fZHeight;
00072
00073 if (fImage) delete fImage;
00074 if (fTimer) delete fTimer;
00075 }
00076
00077
00078 int TGHtml::GetImageAlignment(TGHtmlElement *p)
00079 {
00080
00081
00082 const char *z;
00083 int i;
00084 int result;
00085
00086 static struct {
00087 const char *zName;
00088 int iValue;
00089 } aligns[] = {
00090 { "bottom", IMAGE_ALIGN_Bottom },
00091 { "baseline", IMAGE_ALIGN_Bottom },
00092 { "middle", IMAGE_ALIGN_Middle },
00093 { "top", IMAGE_ALIGN_Top },
00094 { "absbottom", IMAGE_ALIGN_AbsBottom },
00095 { "absmiddle", IMAGE_ALIGN_AbsMiddle },
00096 { "texttop", IMAGE_ALIGN_TextTop },
00097 { "left", IMAGE_ALIGN_Left },
00098 { "right", IMAGE_ALIGN_Right },
00099 };
00100
00101 z = p->MarkupArg("align", 0);
00102 result = IMAGE_ALIGN_Bottom;
00103 if (z) {
00104 for (i = 0; i < int(sizeof(aligns) / sizeof(aligns[0])); i++) {
00105 if (strcasecmp(aligns[i].zName, z) == 0) {
00106 result = aligns[i].iValue;
00107 break;
00108 }
00109 }
00110 }
00111 return result;
00112 }
00113
00114
00115 void TGHtml::ImageChanged(TGHtmlImage *pImage, int newWidth, int newHeight)
00116 {
00117
00118
00119
00120
00121
00122
00123
00124
00125 TGHtmlImageMarkup *pElem;
00126
00127 if (pImage->fW != newWidth || pImage->fH != newHeight) {
00128
00129
00130 for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
00131 pElem->fW = newWidth;
00132 pElem->fH = newHeight;
00133 }
00134 fFlags |= RELAYOUT;
00135 pImage->fW = newWidth;
00136 pImage->fH = newHeight;
00137 RedrawEverything();
00138 } else {
00139 #if 0
00140 for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
00141 pElem->fRedrawNeeded = 1;
00142 }
00143 fFlags |= REDRAW_IMAGES;
00144 ScheduleRedraw();
00145 #else
00146 for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
00147 pElem->fRedrawNeeded = 1;
00148 DrawRegion(pElem->fX, pElem->fY - pElem->fAscent, pElem->fW, pElem->fH);
00149 }
00150 #endif
00151 }
00152 }
00153
00154
00155 TGHtmlImage *TGHtml::GetImage(TGHtmlImageMarkup *p)
00156 {
00157
00158
00159
00160 const char *zWidth;
00161 const char *zHeight;
00162 const char *zSrc;
00163 TGHtmlImage *pImage;
00164
00165 if (p->fType != Html_IMG) { CANT_HAPPEN; return 0; }
00166
00167 zSrc = p->MarkupArg("src", 0);
00168 if (zSrc == 0) return 0;
00169
00170 zSrc = ResolveUri(zSrc);
00171 if (zSrc == 0) return 0;
00172
00173 zWidth = p->MarkupArg("width", "");
00174 zHeight = p->MarkupArg("height", "");
00175
00176
00177
00178
00179 for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
00180 if (strcmp(pImage->fZUrl, zSrc) == 0
00181 && strcmp(pImage->fZWidth, zWidth) == 0
00182 && strcmp(pImage->fZHeight, zHeight) == 0) {
00183 delete [] zSrc;
00184 return pImage;
00185 }
00186 }
00187
00188 TImage *img = LoadImage(zSrc, atoi(zWidth), atoi(zHeight));
00189
00190 if (img) {
00191 pImage = new TGHtmlImage(this, zSrc, zWidth, zHeight);
00192 pImage->fImage = img;
00193
00194
00195
00196 ImageChanged(pImage, img->GetWidth(), img->GetHeight());
00197 pImage->fPNext = fImageList;
00198 fImageList = pImage;
00199 } else {
00200 pImage = 0;
00201 }
00202
00203 delete [] zSrc;
00204
00205 return pImage;
00206 }
00207
00208
00209 static TImage *ReadRemoteImage(const char *url)
00210 {
00211
00212
00213 TImage *image = 0;
00214 FILE *tmp;
00215 char *buf;
00216 TUrl fUrl(url);
00217
00218 TString msg = "GET ";
00219 msg += fUrl.GetProtocol();
00220 msg += "://";
00221 msg += fUrl.GetHost();
00222 msg += ":";
00223 msg += fUrl.GetPort();
00224 msg += "/";
00225 msg += fUrl.GetFile();
00226 msg += "\r\n";
00227
00228 TString uri(url);
00229 if (!uri.BeginsWith("http://") || uri.EndsWith(".html"))
00230 return 0;
00231 TSocket s(fUrl.GetHost(), fUrl.GetPort());
00232 if (!s.IsValid())
00233 return 0;
00234 if (s.SendRaw(msg.Data(), msg.Length()) == -1)
00235 return 0;
00236 Int_t size = 1024*1024;
00237 buf = (char *)calloc(size, sizeof(char));
00238 if (s.RecvRaw(buf, size) == -1) {
00239 free(buf);
00240 return 0;
00241 }
00242 TString pathtmp = TString::Format("%s/%s", gSystem->TempDirectory(),
00243 gSystem->BaseName(url));
00244 tmp = fopen(pathtmp.Data(), "wb");
00245 if (!tmp) {
00246 free(buf);
00247 return 0;
00248 }
00249 fwrite(buf, sizeof(char), size, tmp);
00250 fclose(tmp);
00251 free(buf);
00252 image = TImage::Open(pathtmp.Data());
00253 if (!image->IsValid()) {
00254 delete image;
00255 image = 0;
00256 }
00257 gSystem->Unlink(pathtmp.Data());
00258 return image;
00259 }
00260
00261
00262 TImage *TGHtml::LoadImage(const char *url, int w, int h)
00263 {
00264
00265
00266
00267 TImage *image = 0;
00268
00269
00270
00271 TString uri(url);
00272 if (uri.BeginsWith("http://") && !uri.EndsWith(".html"))
00273 image = ReadRemoteImage(url);
00274 else
00275 image = TImage::Open(url);
00276 if (image) {
00277 if (!image->IsValid()) {
00278 delete image;
00279 image = 0;
00280 return 0;
00281 }
00282 if ((w > 0 && h > 0) && ((w != (int)image->GetWidth()) ||
00283 (h != (int)image->GetHeight()))) {
00284 image->Scale(w, h);
00285 }
00286 }
00287 return image;
00288 }
00289
00290
00291 const char *TGHtml::GetPctWidth(TGHtmlElement *p, char *opt, char *ret)
00292 {
00293
00294
00295
00296 int n, m, val;
00297 const char *tz, *z;
00298 TGHtmlElement *pElem = p;
00299
00300 z = pElem->MarkupArg(opt, "");
00301 if (!strchr(z, '%')) return z;
00302 if (!sscanf(z, "%d", &n)) return z;
00303 if (n < 0 || n > 100) return z;
00304 if (opt[0] == 'h') {
00305 val = fCanvas->GetHeight() * 100;
00306 } else {
00307 val = fCanvas->GetWidth() * 100;
00308 }
00309 if (!fInTd) {
00310 snprintf(ret, 15, "%d", val / n);
00311 } else {
00312 while (pElem && pElem->fType != Html_TD) pElem = pElem->fPPrev;
00313 if (!pElem) return z;
00314 tz = pElem->MarkupArg(opt, 0);
00315 if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
00316 snprintf(ret, 15, "%d", m * 100 / n);
00317 return ret;
00318 }
00319 pElem = ((TGHtmlCell *)pElem)->fPTable;
00320 if (!pElem) return z;
00321 tz = pElem->MarkupArg(opt, 0);
00322 if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
00323 snprintf(ret, 15, "%d", m * 100 / n);
00324 return ret;
00325 }
00326 return z;
00327 }
00328 return ret;
00329 }
00330
00331
00332 int TGHtml::GetImageAt(int x, int y)
00333 {
00334
00335
00336
00337
00338 TGHtmlBlock *pBlock;
00339 TGHtmlElement *pElem;
00340
00341
00342 for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
00343 if (pBlock->fTop > y || pBlock->fBottom < y ||
00344 pBlock->fLeft > x || pBlock->fRight < x) {
00345 continue;
00346 }
00347 for (pElem = pBlock->fPNext; pElem; pElem = pElem->fPNext) {
00348 if (pBlock->fBNext && pElem == pBlock->fBNext->fPNext) break;
00349 if (pElem->fType == Html_IMG) {
00350 return TokenNumber(pElem);
00351 }
00352 }
00353 }
00354
00355 return -1;
00356 }