//|
int Fl_Simple_Html::readWord(_FlString &c) {
for (char done=0; done==0; ) {
if (inFile) {
if (!crsr) {
if (!fgets(lineBuffer, LINE_SZE, inFile)) return 0;
c = crsr = lineBuffer;
}
if ((*crsr==0) || strchr("\n\r", *crsr)) { crsr=0; continue; }
} else if (inText) {
if (!crsr) crsr = (char*)inText;
if (*crsr==0) return 0;
if (strchr("\n\r", *crsr)) { crsr++; continue; }
} else {
return 0;
}
//: skip white noise
while (strchr(" \014\t", *crsr)) crsr++;
if (*crsr=='<') {
c = crsr; crsr++;
break;
}
if (*crsr=='>' || *crsr=='=') {
c = crsr; crsr++; return 1;
}
if ((*crsr==0) || strchr("\n\r", *crsr)) continue;
c = crsr; break;
}
while ((*crsr) && (strchr("\n\r =<>\014\t", *crsr)==0)) crsr++;
return crsr-c;
}
//|
//| read the following argument to a tag word
//| I assume that there is no CR/LF etc. here
//|
int Fl_Simple_Html::readArg(_FlString &c) {
if (*crsr!='=') return 0;
crsr++;
if (*crsr=='"') {
c = ++crsr;
while ((*crsr) && (*crsr!='"')) crsr++;
crsr++; //: skip closing quote
return crsr-c-1;
} else {
c = crsr;
while ((*crsr) && (strchr("\n\r \"<>\014\t", *crsr)==0)) crsr++;
}
return crsr-c;
}
//|
//| flush the current line contents to the browser
//|
void Fl_Simple_Html::flush() {
static char blue[] = "\0\0\0\0\0\0\0\0\0";
const char *H[] = { "", "@S28", "@S24", "@S19", "@S15", "@S13", "@S11" };
const char *S[] = { "", "@S9", "@S11", "@S13", "@S15", "@S19", "@S24", "@S28" };
char fmt[255] = "";
if (!*blue) sprintf((char*)blue, "@C%d", FL_BLUE);
if (outCrsr == outBuffer) return; //: don't flush empty lines
*outCrsr = 0;
if (flags&FLAG_CENTER) strcat(fmt, "@c");
if (flags&FLAG_RIGHT) strcat(fmt, "@r");
if (flags&FLAG_TITLE) strcat(fmt, "@m@b@c");
if (flags&FLAG_ITALICS) strcat(fmt, "@i");
if (flags&FLAG_TELE) strcat(fmt, "@t");
if (flags&FLAG_FSIZE && fsize>=1 && fsize <=7) strcat(fmt, S[fsize]);
if (flags&FLAG_HREF) strcat(fmt, blue);
if (flags&(FLAG_ULINE/*|FLAG_HREF*/)) strcat(fmt, "@u"); //+ underlining the whole line looks pretty ugly!
if ((flags&FLAG_BOLD)||heading) strcat(fmt, "@b");
if ((heading>0)&&(heading<=6)) strcat(fmt, H[heading]);
strcat(fmt, "@.");
for (int i=3*(td?td-1:0)+indent-1+dl; i>0; i--) strcat(fmt, "\t");
if (flags&FLAG_BULLET) strcat(fmt, "o");
if (indent||dl) strcat(fmt, "\t");
add(fmt, outBuffer);
outCrsr = outBuffer;
flags &= ~FLAG_BULLET;
flags &= ~clearFlags;
clearFlags = 0;
}
//|
//| add a word to the current line. If the line gets to long, then flush it
//| with the neccesary attributes
//+ we currently define a word wrap when we hit 64 characters which is of course wrong.
//+ We should keep track of fonts and pixel sizes instead!
//|
int Fl_Simple_Html::addWord(const char *word, int n) {
int ret = 0;
//: remove all nasty control characters except TAB
char *buf = (char*)malloc(n+1); memcpy(buf, word, n); buf[n] = 0;
char *src = buf, *dst = buf;
while (*src) {
if (*src=='&') {
if (strnicmp(""", src, 6)==0) { *dst++ = '"'; src+=6; continue; }
if (strnicmp(" ", src, 6)==0) { *dst++ = ' '; src+=6; continue; }
if (strnicmp("©", src, 6)==0) { *dst++ = '('; *dst++ = 'C'; *dst++ = ')'; src+=6; continue; }
if (strnicmp("®", src, 5)==0) { *dst++ = '('; *dst++ = 'R'; *dst++ = ')'; src+=5; continue; }
if (strnicmp("&", src, 5)==0) { *dst++ = '&'; src+=5; continue; }
if (strnicmp("<", src, 4)==0) { *dst++ = '<'; src+=4; continue; }
if (strnicmp(">", src, 4)==0) { *dst++ = '>'; src+=4; continue; }
}
if (!iscntrl(*src)) *dst++ = *src;
src++;
}
n = dst-buf;
if (n>WORD_WRAP) { //: this word is too long to fit in the line, so we flush the current line and give this word it's very own line
flush();
add("@.", buf, n);
free(buf);
return 2; //: we created 2 lines!
}
if (n+(outCrsr-outBuffer)>=WORD_WRAP) { //: >= for seperating ' ' character
flush();
ret = 1;
}
if ((outBuffer!=outCrsr)&&(outCrsr[-1]!='\t')) *outCrsr++ = ' ';
memmove(outCrsr, buf, n);
free(buf);
outCrsr += n;
return ret; //: return 1 if we started a new line
}
//|
//| tags proved that this is an HTML. Go and interprete it
//|
int Fl_Simple_Html::readHtml() {
outBuffer = outCrsr = (char*)malloc(LINE_SZE);
rewind();
flags = clearFlags = 0;
indent = 0; td = dl = 0; heading = 0; fsize = 0; fontCnt = 0;
char *c = 0;
int n = 0;
for (;;) {
n = readWord(c);
if (n==0) break;
if (*c=='<') {
if (n==2) {
if (strnicmp(" tags...
flush(); if (!addWord(" ", 1)) flush();
} else if (strnicmp("') {
crsr = c; break;
} else if (strnicmp("href=", c, n+1)==0) {
flush(); flags |= FLAG_HREF; //+ sorry, but links currently need their own single line
n = readArg(c); if (n) addHref(c, n);
} else if (strnicmp("name=", c, n+1)==0) {
n = readArg(c); if (n) addAnchor(c, n);
}
}
}
} else if (n==3) {
if (strnicmp("
0) indent--;
} else if (strnicmp("0) indent--;
} else if (strnicmp("') {
crsr = c; break;
} else if (strnicmp("size=", c, n+1)==0) {
if (c[n+1]=='-') fsize-=atoi(c+n+2);
else if (c[n+1]=='+') fsize+=atoi(c+n+2);
else if (isdigit(c[n+1])) fsize=atoi(c+n+1);
else fsize = 4;
if (fsize<1) fsize = 1; if (fsize>7) fsize = 7;
flush(); flags |= FLAG_FSIZE;
readArg(c); fontCnt = 0;
}
}
fontCnt++;
} else if (strnicmp("0) fontCnt--;
if (fontCnt==0) { clearFlags |= FLAG_FSIZE; flush(); fsize = 4; } //+ actually we need to track for the _corresponding_
}
} else if (n==7) {
if (strnicmp("
0) indent--; if (!addWord(" ", 1)) flush();
}
} /*else {
char buf[80]; memcpy(buf, c, n); buf[n] = 0;
PRINTF1("Skipped tag '%s>'\n", buf);
} */
gotoTagEnd();
} else addWord(c, n);
}
flush();
free(outBuffer);
return 1;
}
//|
//| There were no signs of an HTML, so go and read simple text
//|
int Fl_Simple_Html::readText() {
rewind();
if (inFile) {
while (fgets(lineBuffer, LINE_SZE, inFile)) {
add("@f@.", lineBuffer);
}
} else if (inText) {
const char *src = inText, *start = inText;
while (*src) {
if (*src=='\n') {
add("@f@.", start, src-start);
start = src;
}
src++;
}
if (start!=src) add("@f@.", start, src-start);
}
return 1;
}
//|
//| test for the input type and call the appropiate interpreter
//|
int Fl_Simple_Html::read() {
clear();
char *crsr = 0L;
int n = readWord(crsr);
char isHtml = 0;
if (n==9 && strnicmp(crsr, "o this: previously created Html widget, can be visible at this point
//| ->o filename: absolute or relative filename of a local HTML file, optional #anchor
//| ->o path: optional path to make filename relative to
//| o-> return: 1 for success, 0 if it could not open the html file
//|
int Fl_Simple_Html::load(const char *filename, const char *path) {
int ret = 1;
char oldPath[256];
getcwd(oldPath, 256); //: remember the start directory to restore it later
inText = 0L; crsr = 0L;
if (path) chdir(path); else if (docPath) chdir(docPath); //: if we got a path, use it. Otherwise use the path of the previous doc
char *fn = strdup(filename); //: copy the filename and clip the #anchor part off.
char *a = strrchr(fn, '#');
if (a) *a++ = 0;
if (strlen(fn)) { //: if we still have a filename, open the file. Else just jump to the #anchor
clear(); //: clear the current document
char newPath[1024], *fnn;
if (docPath) free(docPath); //: remove the previous path name
filename_absolute(newPath, fn); //: find the absolute filename and path to the given filename
if (prevUrl_) free(prevUrl_); prevUrl_ = url_; //: (not really used yet)
url_ = strdup(newPath); //: duplicate the new absolute filename and path
fnn=(char*)filename_name(newPath); //: find the filename path
docPath = strndup(newPath, fnn-newPath); //: copy the path part, so we know where links in this document are relative to.
chdir(docPath); //: make that path current
inFile = fopen(fnn, "rb"); //: now open the file
if (!inFile) { //: if that fails, let the user know, why
Fl_Browser::clear();
Fl_Browser::add("Can't open url");
Fl_Browser::add(newPath);
Fl_Browser::add(strerror(errno));
ret = 0; goto bail; //: don't leave without freeing memory and restoring the current dir
//: if you don't like the 'goto', think of it as throwing an exception - and implement it ;-)
}
lineBuffer = (char*)malloc(LINE_SZE);
ret = read(); //: go ahead, read or interprete the file
free(lineBuffer);
fclose(inFile);
}
if (a) gotoAnchor(a); //: remember? We extracted an #anchor. Now jump to that anchor.
bail:
free(fn);
if (path) chdir(oldPath); //: restore the old path
return ret;
}
//|
//| interprete a text string
//|
int Fl_Simple_Html::read(const char *html, const char *path) {
char oldPath[256];
getcwd(oldPath, 256);
if (path) {
if (docPath) free(docPath);
docPath = strdup(path);
}
if (docPath) chdir(docPath);
inFile = 0;
inText = html; crsr = 0L;
int ret = read();
if (path) chdir(oldPath);
return ret;
}