home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-25 | 37.1 KB | 1,544 lines |
- // **************************************************************************
- // Copyright 1996 David Allison
- //
- // VV VV IIIIII SSSSS TTTTTT AA
- // VV VV II SS TT AA AA
- // VV VV II SSSS TT AA AA
- // VV VV II SS TT AAAAAAAA
- // VV IIIIII SSSS TT AA AA
- //
- // MULTI-THREADED C++ WIMP CLASS LIBRARY
- // for RISC OS
- // **************************************************************************
- //
- // P U B L I C D O M A I N L I C E N C E
- // -------------------------------------------
- //
- // This library is copyright. You may not sell the library for
- // profit, but you may sell products which use it providing
- // those products are presented as executable code and are not
- // libraries themselves. The library is supplied without any
- // warranty and the copyright owner cannot be held responsible for
- // damage resulting from failure of any part of this library.
- //
- // See the User Manual for details of the licence.
- //
- // *************************************************************************
- //
- // HTML viewer
- //
-
- #include "Vista:vista.h"
- #include "hyperview.h"
- #include <swis.h>
- #include <kernel.h>
- #include <string.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
-
- int string_compare (char *s1, char *s2)
- {
- while (*s1)
- {
- if (tolower (*s1) != tolower (*s2))
- break ;
- s1++ ;
- s2++ ;
- }
- return tolower (*s1) - tolower (*s2) ;
- }
-
-
- char *stralloc (char *s)
- {
- char *p ;
- p = new char [strlen(s)+1] ;
- if (p == NULL)
- throw "Out of memory" ;
- strcpy (p,s) ;
- return p ;
- }
-
- HTMLObject::HTMLObject(Viewer *v)
- {
- viewer = v ;
- v->add_object (this) ;
- }
-
- HTMLObject::~HTMLObject()
- {
- }
-
- ParagraphBody::ParagraphBody (Paragraph *p,Window *w, char *name, int fhandle, int x0, int y0, int width, int priority, char *menu)
- : FontObject (w,name,fhandle,x0,y0,width,priority,menu)
- {
- this->p = p ;
- hyperlink = 0 ;
- url = NULL ;
- }
-
- ParagraphBody::~ParagraphBody()
- {
- if (url != NULL)
- delete [] url ;
- }
-
- void ParagraphBody::pointer (int entering)
- {
- if (hyperlink)
- if (entering)
- p->viewer->print (url) ;
- else
- p->viewer->print ("") ;
- }
-
-
- void ParagraphBody::click (int mx, int my, int button)
- {
- if (hyperlink)
- {
- char filename[256] ;
- char anchor[256] ;
- if (p->viewer->parse_url (url, filename, anchor))
- {
- p->viewer->follow_hyperlink (filename, anchor) ;
- }
- }
- }
-
- void ParagraphBody::set_url(char *url)
- {
- this->url = stralloc (url) ;
- }
-
-
- PointerIcon::PointerIcon (Window *w,Icon *temp, int x0, int y0, int width, int height, ParagraphBody *body)
- : Icon (w, temp, x0, y0)
- {
- resize (width,height) ;
- this->body = body ;
- }
-
- PointerIcon::~PointerIcon()
- {
- }
-
- void PointerIcon::click (int mx, int my, int button, int icon)
- {
- body->click (mx, my, button) ;
- }
-
-
- void Paragraph::set_last_gap(int units)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- if (body->last_line == NULL)
- return ;
- r.r[1] = 0 ;
- r.r[2] = units ;
- if ((e = _kernel_swi (Font_Converttopoints, &r, &r)) != NULL)
- throw e ;
- body->last_line->y += r.r[2] ;
- body->y0 -= units ;
- }
-
- //
- // return the height of the last line in OS units
- //
-
- int Paragraph::last_line_height()
- {
- if (body->last_line == NULL)
- return 0 ;
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- r.r[1] = 0 ;
- r.r[2] = body->last_line->height ;
- if ((e = _kernel_swi (Font_ConverttoOS, &r, &r)) != NULL)
- throw e ;
- return r.r[2] ;
- }
-
-
- Paragraph::Paragraph (Viewer *v, int x, int y, int width, int priority)
- : HTMLObject (v)
- {
- body = new ParagraphBody (this, v, "", v->normal_font(), x, y, width, priority) ;
- }
-
- Paragraph::~Paragraph()
- {
- delete body ;
- }
-
- void Paragraph::redraw()
- {
- viewer->do_redraw (body->x0, body->y0, body->x1, body->y1) ;
- }
-
- void Paragraph::add_text(char *text)
- {
- body->add_text (text) ;
- // ::print ("body text = %s",body->text+2) ;
- }
-
- void Paragraph::finish()
- {
- body->finish() ;
- // redraw() ;
- }
-
- int Paragraph::height()
- {
- return body->height() ;
- }
-
- void Paragraph::normal()
- {
- current_font = viewer->normal_font() ;
- body->set_font(current_font) ;
- body->set_colour (255,255,255,0,0,0,14) ; // black
- }
-
- void Paragraph::system()
- {
- current_font = viewer->system_font() ;
- body->set_font(current_font) ;
- body->set_colour (255,255,255,0,0,0,14) ; // black
- }
-
- void Paragraph::set_font(int font)
- {
- current_font = font ;
- body->set_font(current_font) ;
- }
-
- void Paragraph::bold()
- {
- if (current_font == viewer->italic_font())
- current_font = viewer->bold_italic_font() ;
- else
- current_font = viewer->bold_font() ;
- body->set_font(current_font) ;
- }
-
- void Paragraph::italic()
- {
- if (current_font == viewer->bold_font())
- current_font = viewer->bold_italic_font() ;
- else
- current_font = viewer->italic_font() ;
- body->set_font(current_font) ;
- }
-
- void Paragraph::header(int level)
- {
- body->set_font(viewer->header_font(level-1)) ;
- }
-
- void Paragraph::begin_hyperlink()
- {
- body->set_colour (255,255,255,0,0,255,14) ; // set blue
- body->begin_underline() ;
- body->hyperlink = 1 ;
- }
-
- void Paragraph::end_hyperlink()
- {
- body->set_colour (255,255,255,0,0,0,14) ; // set black
- body->end_underline() ;
- }
-
- int Paragraph::width()
- {
- return body->width() ;
- }
-
- void Paragraph::set_indent(int i)
- {
- body->set_indent (i) ;
- }
-
- void Paragraph::read_position (int &x, int &y)
- {
- x = body->x0 ;
- y = body->y1 ;
- }
-
- void Paragraph::set_url(char *url)
- {
- body->set_url (url) ;
- }
-
-
- Image::Image(Viewer *v, char *filename, int x, int y, int priority)
- : HTMLObject (v)
- {
- image = new DrawObject (v, "", filename, x, y) ;
- }
-
-
- Image::~Image()
- {
- delete image ;
- }
-
- int Image::height()
- {
- return image->y1 - image->y0 ;
- }
-
- int Image::width()
- {
- return image->x1 - image->x0 ;
- }
-
-
- HRuleObject::HRuleObject(Window *w, int y, int width, int priority)
- : Object (w, "HR", priority, 0)
- {
- x0 = 4 << w->task->xeigfactor ;
- x1 = width - (4 << w->task->xeigfactor) ;
- y1 = y ;
- y0 = y - (1 << w->task->yeigfactor) ;
- }
-
- HRuleObject::~HRuleObject()
- {
- }
-
- void HRuleObject::redraw (int x0, int y0, int x1, int y1)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int sx, sy ; // start screen x and y coords
- int ex ; // end screen coords
- if (x0 <= this->x1 && x1 >= this->x0 && y0 <= this->y1 && y1 >= this->y0)
- {
- sx = window->x0 + this->x0 - window->scx ; // screen x
- sy = window->y1 + this->y0 - window->scy ; // screen y
- ex = window->x0 + this->x1 - window->scx ; // screen x
- r.r[0] = 3 ;
- _kernel_swi (Wimp_SetColour, &r, &r) ;
-
- r.r[0] = 4 ;
- r.r[1] = sx ;
- r.r[2] = sy ;
- if ((e = _kernel_swi (OS_Plot, &r, &r)) != NULL)
- throw e ;
-
- r.r[0] = 5 ;
- r.r[1] = ex ;
- r.r[2] = sy ;
- _kernel_swi (OS_Plot, &r, &r) ;
- r.r[0] = 0 ;
- _kernel_swi (Wimp_SetColour, &r, &r) ;
-
- r.r[0] = 4 ;
- r.r[1] = sx ;
- r.r[2] = sy - (1 << window->task->yeigfactor);
- if ((e = _kernel_swi (OS_Plot, &r, &r)) != NULL)
- throw e ;
-
- r.r[0] = 5 ;
- r.r[1] = ex ;
- r.r[2] = sy - (1 << window->task->yeigfactor) ;
- _kernel_swi (OS_Plot, &r, &r) ;
- }
- }
-
- HLine::HLine (Viewer *v, int y, int width, int priority)
- : HTMLObject (v)
- {
- line = new HRuleObject (v, y, width, priority) ;
- }
-
- HLine::~HLine()
- {
- delete line ;
- }
-
- int HLine::height()
- {
- return line->y1 - line->y0 ;
- }
-
- int HLine::width()
- {
- return line->x1 - line->x0 ;
- }
-
-
- Controls::Controls(Viewer *v)
- : Window (v,"control",A_LEFT)
- {
- viewer = v ;
- }
-
- Controls::~Controls()
- {
- }
-
-
- void Controls::click (int mx, int my, int button, int icon)
- {
- switch (icon)
- {
- case BACK:
- viewer->back() ;
- break ;
- case FORWARD:
- viewer->forward() ;
- break ;
- case HOME:
- // viewer->task->show_threads() ;
- viewer->home() ;
- break ;
- }
- }
-
-
- Display::Display(Window *parent)
- : Window (parent,"display",A_BOTTOM)
- {
- output = new Icon (this, 0) ;
- }
-
- Display::~Display()
- {
- }
-
- void Display::print (char *text)
- {
- output->print (text) ;
- }
-
-
- char Viewer::line[4096] ;
- char Viewer::sentence[4096] ;
-
-
- Viewer::Viewer(HyperView *h)
- : Window (h, "viewer")
- {
- controls = new Controls(this) ;
- display = new Display (this) ;
- objects = NULL ;
- last_object = NULL ;
- normal_fhandle = h->open_font ("Homerton.Medium", 12, 12) ;
- bold_fhandle = h->open_font ("Homerton.Bold", 12, 12) ;
- italic_fhandle = h->open_font ("Homerton.Medium.Oblique", 12, 12) ;
- bold_italic_fhandle = h->open_font ("Homerton.Bold.Oblique", 12, 12) ;
- header_fonts[0] = h->open_font ("Homerton.Bold",24,24) ;
- header_fonts[1] = h->open_font ("Homerton.Bold",20,20) ;
- header_fonts[2] = h->open_font ("Homerton.Bold.Oblique",16,16) ;
- header_fonts[3] = h->open_font ("Homerton.Bold.Oblique",14,14) ;
- header_fonts[4] = h->open_font ("Homerton.Bold.Oblique",13,13) ;
- header_fonts[5] = h->open_font ("Homerton.Bold.Oblique",12,12) ;
- system_fhandle = h->open_font ("System.Fixed", 12, 12) ;
- Window::Info *inf = info() ;
- width = inf->box.x1 - inf->box.x0 ;
- min_height = inf->extent.y1 - inf->extent.y0 ;
- anchors = NULL ;
- next = NULL ;
- prev = NULL ;
- context_stack = NULL ;
- current_context = NULL ;
- hyperview = h ;
- h->add_viewer (this) ;
- sp = 0 ;
- preformatted = true ;
- eol = false ;
- num_bytes = 0 ;
- template_pointer_icon = new Icon (this, 0) ;
- template_pointer_icon->move_to (-1000,1000) ; // move out of the way
- strcpy (current_document,"") ;
- }
-
- Viewer::~Viewer()
- {
- }
-
- void Viewer::close()
- {
- hyperview->delete_viewer(this) ;
- Window::close() ;
- }
-
- //
- // Display a file containing HTML format test in a viewer
- //
-
-
- void Viewer::display_file(char *filename, bool new_ctx)
- {
- char buffer[256] ;
- char *file = filename ;
- char *p = strrchr (filename,'.') ; // last . in filename
- if (p == NULL) // any path?
- {
- if (strcmp (filename, current_document) == 0)
- {
- if (new_ctx)
- new_context() ; // open new context
- return ;
- }
- sprintf (buffer, "%s.%s",document_root,filename) ;
- file = buffer ;
- }
- else
- {
- if (strcmp (p+1, current_document) == 0)
- {
- if (new_ctx)
- new_context() ; // open new context
- return ;
- }
- }
- if ((fp = fopen (file, "r")) == NULL)
- {
- sprintf (buffer, "Unable to open file %s",file) ;
- throw buffer ;
- }
- if (p != NULL)
- {
- strncpy (document_root, filename, p - filename) ;
- document_root[p-filename] = 0 ;
- strcpy (current_document,p+1) ;
- }
- else
- strcpy (current_document, filename) ;
- num_bytes = 0 ;
- scroll_to(0,0) ;
- do_redraw() ;
- next_line() ;
- process_html() ;
- if (-y > min_height)
- set_height (-y) ; // set the window height
- else
- set_height (min_height) ;
- do_redraw() ;
- fclose (fp) ;
- if (new_ctx)
- new_context() ; // open new context
- }
-
- void Viewer::next_line()
- {
- for (;;)
- {
- if (fgets (line, 4096, fp) == NULL)
- longjmp(eof_state,1) ;
- else
- {
- ch = line ;
- if (preformatted)
- break ;
- while (isspace (*ch) && *ch != 0)
- ch++ ;
- if (*ch == 0)
- continue ;
- else
- break ;
- }
- }
- }
-
-
- int Viewer::next_char()
- {
- converted = true ;
- char buf[1024] ;
- if (*ch == 0)
- next_line() ;
- num_bytes++ ;
- if ((num_bytes % 100) == 0)
- {
- sprintf (buf,"Read %d bytes",num_bytes) ;
- display->print (buf) ;
- }
- if (*ch == '&')
- {
- int i = 0 ;
- ch++ ;
- while (*ch != ';')
- buf[i++] = *ch++ ;
- buf[i] = 0 ;
- ch++ ;
- if (buf[0] == '#')
- return atoi (buf+1) ;
- else
- {
- if (strcmp (buf,"lt") == 0)
- return '<' ;
- if (strcmp (buf,"gt") == 0)
- return '>' ;
- if (strcmp (buf,"amp") == 0)
- return '&' ;
- if (strcmp (buf,"quot") == 0)
- return '"' ;
- return '?' ;
- }
- }
- converted = false ;
- return *ch++ ;
- }
-
-
- int Viewer::word()
- {
- int c ;
- int i = 0 ;
- int prespaces = 0 ;
- bool has_paras ;
-
- if (eol)
- {
- eol = false ;
- next_line() ;
- return EOL ;
- }
- while (isspace (*ch))
- {
- if (preformatted && *ch == '\n')
- {
- prespaces = 0 ;
- next_line() ;
- return P ;
- }
- prespaces++ ;
- next_char() ;
- }
- c = next_char() ;
- if (!converted && c == '<')
- {
- bool close_command = false ;
- c = next_char() ;
- if (c == '!')
- {
- c = next_char() ;
- while (c != '>') // skip to end of HTML command
- c = next_char() ;
- return word() ;
- }
- if (c == '/')
- {
- close_command = true ;
- c = next_char() ;
- }
- while (c != '>' && !isspace (c))
- {
- spelling[i++] = c ;
- c = next_char() ;
- }
- spelling[i] = 0 ;
- if ((i = reserved_word(has_paras)) != -1)
- {
- if (!has_paras)
- {
- while (c != '>') // skip to end of HTML command
- c = next_char() ;
- }
- if (close_command)
- return i | END ;
- return i ;
- }
- while (c != '>') // skip to end of HTML command
- c = next_char() ;
- return word() ;
- }
- else
- {
- if (preformatted)
- {
- while (prespaces--)
- spelling[i++] = ' ' ;
- spelling[i++] = c ;
- while (i < 132 && *ch != '\n' && *ch != 0 && *ch != '<') // copy until end of line
- spelling[i++] = next_char() ;
- spelling[i] = 0 ; // terminate it
- eol = *ch == '\n' ;
- }
- else
- {
- do
- {
- spelling[i++] = c ;
- c = next_char() ;
- } while (!isspace (c) && c != '<') ;
- ch-- ;
- spelling[i] = 0 ;
- }
- return WORD ;
- }
- }
-
- //
- // parse toekns inside HTML command
- //
-
- int Viewer::token()
- {
- int c ;
- int i = 0 ;
- char *ptr ;
- while (isspace (*ch)) next_char() ;
- c = next_char() ;
- if (c == '=')
- return EQUALS ;
- if (c == '>')
- return CEND ;
- else if (c == '"')
- {
- ptr = spelling ;
- while ((c = next_char()) != '"')
- {
- if (c == 0)
- break ;
- *ptr++ = c ;
- }
- *ptr = 0 ;
- return STRING ;
- }
- else if (isdigit(c))
- {
- do
- {
- spelling[i] = c ;
- c = next_char() ;
- i++ ;
- }
- while (isdigit(c)) ;
- spelling[i] = 0 ;
- ch-- ;
- sscanf (spelling, "%d", &value) ;
- return NUMBER ;
- }
- else
- {
- do
- {
- spelling[i++] = c ;
- c = next_char() ;
- } while (isalpha(c)) ;
- ch-- ;
- spelling[i] = 0 ;
- if ((c = html_reserved_word()) != -1)
- return c ;
- return WORD ;
- }
- }
-
- static struct
- {
- char *word ;
- int value ;
- bool parameters ;
- } res_words[] = {
- {"TITLE", Viewer::TITLE, false},
- {"P", Viewer::P, false},
- {"BR", Viewer::BR, false},
- {"IMG", Viewer::IMG, true},
- {"PRE", Viewer::PRE, false},
- {"H1", Viewer::H1, false},
- {"H2", Viewer::H2, false},
- {"H3", Viewer::H3, false},
- {"H4", Viewer::H4, false},
- {"H5", Viewer::H5, false},
- {"H6", Viewer::H6, false},
- {"EM", Viewer::EM, false},
- {"B", Viewer::B, false},
- {"A", Viewer::A, true},
- {"HR", Viewer::HR, false},
- {"HTML", Viewer::HTML, false},
- {"UL", Viewer::UL, false},
- {"OL", Viewer::OL, false},
- {"LI", Viewer::LI, false},
- {NULL, 0}
- } ;
-
-
-
- int Viewer::reserved_word(bool ¶s)
- {
- int i ;
- for (i = 0 ; res_words[i].word != NULL ; i++)
- if (string_compare (res_words[i].word, spelling) == 0)
- {
- paras = res_words[i].parameters ;
- return res_words[i].value ;
- }
- return -1 ;
- }
-
-
- static struct
- {
- char *word ;
- int value ;
- } html_res_words[] = {
- {"NAME", Viewer::NAME},
- {"HREF", Viewer::HREF},
- {"ALIGN", Viewer::ALIGN},
- {"TOP", Viewer::TOP},
- {"MIDDLE", Viewer::MIDDLE},
- {"BOTTOM", Viewer::BOTTOM},
- {"ALT", Viewer::ALT},
- {"ISMAP", Viewer::ISMAP},
- {"SRC", Viewer::SRC},
- {NULL, 0}
- } ;
-
- int Viewer::html_reserved_word()
- {
- int i ;
- for (i = 0 ; html_res_words[i].word != NULL ; i++)
- if (string_compare (html_res_words[i].word, spelling) == 0)
- return html_res_words[i].value ;
- return -1 ;
- }
-
-
- void Viewer::process_html()
- {
- int t ;
- int indent ;
- int font_border ;
- int in_list ;
- int list_number ;
- int list_indent = -32 ;
- int list_type ;
- char buf[256] ;
- Window::Info *inf ;
-
- #if 0
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- r.r[1] = 0 ;
- r.r[2] = FONT_BORDER ;
- if ((e = _kernel_swi (Font_ConverttoOS, &r, &r)) != NULL)
- throw e ;
- font_border = r.r[2] ;
- #endif
- x = 0 ; y = 0 ;
- new_paragraph(system_fhandle) ;
- current_font = system_fhandle ;
- in_list = false ;
- list_type = 0 ;
- if (setjmp (eof_state) == 0)
- {
- for (;;) // EOF will cause longjmp to stop loop
- {
- switch (t = word())
- {
- case HTML:
- preformatted = false ;
- new_paragraph(normal_fhandle) ;
- current_font = normal_fhandle ;
- break ;
- case OL:
- case UL:
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- }
- push (in_list) ;
- push (list_number) ;
- push (list_indent) ;
- push (x) ;
- push (list_type) ;
- list_type = t ; // ordered list
- in_list = true ;
- list_number = 0 ;
- list_indent += 32 ;
- x = list_indent ;
- break ;
- case LI:
- if (!in_list)
- break ;
- if (list_number != 0) // not first item in list
- {
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ; // close previous list item
- paragraph->finish() ;
- y -= paragraph->height() ;
- }
- } // next line
- switch (list_type)
- {
- case UL: // unordered list
- list_number++ ;
- buf[0] = 143 ; // bullet
- buf[1] = 0 ;
- x = list_indent + 16;
- new_paragraph (normal_fhandle) ; // list item number para
- paragraph->add_text (buf) ;
- paragraph->finish() ;
- x = list_indent + 32 ; // move to past item number
- new_paragraph (normal_fhandle) ; // for list item text
- break ;
- case OL: // ordered list
- list_number++ ;
- sprintf (buf,"%d.", list_number) ;
- x = list_indent + 16 ;
- new_paragraph (normal_fhandle) ; // list item number para
- paragraph->add_text (buf) ;
- paragraph->finish() ;
- x = list_indent + 48 ; // move to past item number
- new_paragraph (normal_fhandle) ; // for list item text
- break ;
- }
- break ;
- case (OL|END):
- case (UL|END):
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- list_type = pop() ;
- x = pop() ;
- list_indent = pop() ;
- list_number = pop() ;
- in_list = pop() ;
- new_paragraph(current_font) ;
- break ;
-
- case TITLE:
- sentence[0] = 0 ;
- p = sentence ;
- while ((t = word()) != (TITLE | END))
- append_word (spelling) ;
- set_title (sentence) ;
- sentence[0] = 0 ; p = sentence ;
- break ;
- case HR:
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- }
- y -= 20 ;
- HLine *hline = new HLine (this, y, width, 1) ;
- y -= hline->height() ;
- y -= 20 ;
- if (sentence[0] != 0)
- new_paragraph(current_font) ;
- else
- paragraph->set_indent(0) ;
- break ;
-
- case P:
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- if (-y > min_height)
- set_height (-y) ; // set the window height
- else
- set_height (min_height) ;
- }
- y -= 20 ;
- new_paragraph(current_font) ;
- break ;
- case BR:
- case EOL:
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- new_paragraph(current_font) ;
- }
- else
- paragraph->set_indent(0) ;
- break ;
- case B:
- append_word (" ") ;
- paragraph->add_text (sentence) ;
- sentence[0] = 0 ;
- p = sentence ;
- paragraph->bold() ;
- break ;
- case B|END:
- case EM|END:
- append_word (" ") ;
- paragraph->add_text (sentence) ;
- sentence[0] = 0 ;
- p = sentence ;
- paragraph->set_font(current_font) ;
- break ;
- case EM:
- append_word (" ") ;
- paragraph->add_text (sentence) ;
- sentence[0] = 0 ;
- p = sentence ;
- paragraph->italic() ;
- break ;
- case A: // HTML anchor command
- if (sentence[0] != 0)
- {
- append_word (" ") ;
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- indent = paragraph->width() ;
- y -= paragraph->height() ;
- y += paragraph->last_line_height() + 14 ;
- }
- else
- indent = 0 ;
- new_paragraph(current_font,PARAGRAPH_NORMAL_PRIORITY+1) ;
- paragraph->set_indent (indent) ;
- sentence[0] = 0 ;
- p = sentence ;
- begin_anchor() ;
- break ;
- case A|END:
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- indent = paragraph->width() ;
- y -= paragraph->height() ;
- y += paragraph->last_line_height() + 14 ;
- }
- else
- indent = 0 ;
- end_anchor() ;
- new_paragraph(current_font) ;
- paragraph->set_indent(indent) ;
- sentence[0] = 0 ;
- p = sentence ;
- append_word (" ") ;
- break ;
- case H1:
- case H2:
- case H3:
- case H4:
- case H5:
- case H6:
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- }
- y -= 20 ;
- new_paragraph(current_font) ;
- sentence[0] = 0 ;
- p = sentence ;
- paragraph->header(t - H1 + 1) ;
- break ;
- case H1|END:
- case H2|END:
- case H3|END:
- case H4|END:
- case H5|END:
- case H6|END:
- if (sentence[0] !=0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- y -= 30 ;
- }
- new_paragraph(current_font) ;
- break ;
- case IMG: // image
- int width = 0 , line_height = 0 ;
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- width = paragraph->width() ; // get width of last line of prev para
- line_height = paragraph->last_line_height() ; // height of last line
- }
- y += line_height + 8 ; // move up to base of prev line
- Image *image = insert_image(width + 8) ; // insert the image
- if (image != NULL)
- {
- int image_height = image->height() ;
- if (image_height > line_height)
- paragraph->set_last_gap(image_height - line_height) ;
- indent = width + image->width() + 16 ; // get new indent for next para
- y -= image_height - line_height - 8 ;
- new_paragraph(current_font) ;
- paragraph->set_indent(indent) ;
- }
- else
- new_paragraph(current_font) ;
- break ;
- case PRE:
- if (sentence[0] != 0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- }
- preformatted = true ;
- push (current_font) ;
- new_paragraph(system_fhandle) ;
- current_font = system_fhandle ;
- break ;
- case PRE|END:
- if (sentence[0] !=0)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- }
- preformatted = false ;
- current_font = pop() ;
- new_paragraph(current_font) ;
- break ;
- case WORD:
- append_word (spelling) ;
- break ;
- }
- }
- }
- else // get here on end of file
- {
- if (paragraph != NULL)
- {
- paragraph->add_text (sentence) ;
- paragraph->finish() ;
- y -= paragraph->height() ;
- y -= 80 ;
- }
- }
- }
-
- void Viewer::append_word (char *word)
- {
- int len = p - sentence ;
- if (len > 0)
- {
- if (len + strlen(word) > 4095)
- {
- paragraph->add_text (sentence) ;
- sentence[0] = 0 ;
- p = sentence ;
- }
- *p++ = ' ' ;
- }
- while (*p++ = *word++) ; // copy in word
- p-- ;
- }
-
- void Viewer::new_paragraph(int font, int priority)
- {
- sentence[0] = 0 ;
- p = sentence ;
- paragraph = new Paragraph (this, x, y, width - x, priority) ;
- paragraph->set_font(font) ;
- }
-
- void Viewer::html_error()
- {
- while (token() != CEND) ;
- }
-
- //
- // begin an anchor in a document. This can either be a destination (by use of the NAME attribute)
- // or a hypertext link (by use of the HREF attribute)
- //
-
- void Viewer::begin_anchor()
- {
- int t ;
- while ((t = token()) != CEND)
- {
- switch (t)
- {
- case NAME:
- if (token() != EQUALS)
- {
- html_error() ;
- return ;
- }
- if (token() != STRING)
- {
- html_error() ;
- return ;
- }
- char *name = stralloc (spelling) ;
- current_anchor = insert_anchor (anchors, NULL, name) ;
- break ;
- case HREF:
- if (token() != EQUALS)
- {
- html_error() ;
- return ;
- }
- if (token() != STRING)
- {
- html_error() ;
- return ;
- }
- paragraph->begin_hyperlink() ; // begin a hyper link in the paragraph
- paragraph->set_url (spelling) ;
- current_anchor = NULL ;
- break ;
- }
- }
- }
-
- void Viewer::end_anchor()
- {
- if (current_anchor == NULL)
- {
- int x, y, width, height ;
- paragraph->end_hyperlink() ;
- paragraph->read_position (x, y) ;
- width = paragraph->width() ;
- height = paragraph->height() ;
- PointerIcon *ic = new PointerIcon (this, template_pointer_icon, x, y - height, width, height, paragraph->body) ;
- }
- else
- paragraph->read_position (current_anchor->x, current_anchor->y) ;
- }
-
-
- Anchor *Viewer::insert_anchor (Anchor *t, Anchor **root, char *name)
- {
- Anchor *a ;
- int v ;
- if (t == NULL)
- {
- a = new Anchor ;
- a->left = a->right = NULL ;
- a->x = a->y = 0 ;
- a->name = name ;
- if (root == NULL)
- anchors = a ;
- else
- *root = a ;
- return a ;
- }
- else
- {
- v = string_compare (name, t->name) ;
- if (v < 0)
- return insert_anchor (t->left, &t->left, name) ;
- else
- if (v == 0) // replacing an anchor
- return t ;
- else
- return insert_anchor (t->right, &t->right, name) ;
- }
- }
-
- Anchor *Viewer::find_anchor (Anchor *t, char *name)
- {
- int v ;
- if (t == NULL)
- return NULL ;
- v = string_compare (name, t->name) ;
- if (v < 0)
- return find_anchor (t->left, name) ;
- else
- if (v == 0)
- return t ;
- else
- return find_anchor (t->right, name) ;
- }
-
- void Viewer::delete_anchor (Anchor *t)
- {
- if (t == NULL)
- return ;
- delete [] t->name ;
- delete_anchor (t->left) ;
- delete_anchor (t->right) ;
- }
-
- void Viewer::scroll_to_anchor(char *name)
- {
- Anchor *anchor = find_anchor (anchors,name) ;
- if (anchor != NULL)
- scroll_to (anchor->x, anchor->y) ;
- }
-
-
- Image *Viewer::insert_image(int xpos)
- {
- int t ;
- Image *image = NULL ;
- char filename[256] ;
- while ((t = token()) != CEND)
- {
- switch (t)
- {
- case SRC:
- if (token() != EQUALS)
- {
- html_error() ;
- return NULL ;
- }
- if (token() != STRING)
- {
- html_error() ;
- return NULL ;
- }
- sprintf (filename, "%s.%s",document_root,spelling) ;
- // ::print ("looking for image %s",filename) ;
- try
- image = new Image (this, filename, xpos, y, 1) ;
- catch (_kernel_oserror *)
- image = NULL ;
- break ;
- }
- }
- return image ;
- }
-
-
- //
- // add an HTML object to the list of objects in this viewer
- //
-
- void Viewer::add_object(HTMLObject *o)
- {
- o->next = NULL ;
- if (objects == NULL)
- objects = last_object = o ;
- else
- {
- last_object->next = o ;
- o->prev = last_object ;
- last_object = o ;
- }
- }
-
- void Viewer::clear()
- {
- HTMLObject *o, *nexto ;
- for (o = objects ; o != NULL ; o = nexto)
- {
- nexto = o->next ;
- delete o ;
- }
- objects = NULL ;
- last_object = NULL ;
- Icon *i, *nexti ;
- for (i = icons ; i != NULL ; i = nexti)
- {
- nexti = i->next ;
- if (i != template_pointer_icon)
- delete i ;
- }
- icons = template_pointer_icon ;
- }
-
-
- void Viewer::set_home_document(char *filename)
- {
- strcpy (home_document, filename) ;
- }
-
- int Viewer::normal_font()
- {
- return normal_fhandle ;
- }
-
- int Viewer::bold_font()
- {
- return bold_fhandle ;
- }
-
- int Viewer::italic_font()
- {
- return italic_fhandle ;
- }
-
- int Viewer::bold_italic_font()
- {
- return bold_italic_fhandle ;
- }
-
- int Viewer::header_font(int level)
- {
- return header_fonts[level] ;
- }
-
- int Viewer::system_font()
- {
- return system_fhandle ;
- }
-
-
- void Viewer::print (char *format...)
- {
- va_list arg ;
- char buf[256] ;
- va_start (arg,format) ;
- vsprintf (buf, format, arg) ;
- display->print (buf) ;
- }
-
-
- bool Viewer::parse_url (char *url, char *filename, char *anchor)
- {
- char buf[1024] ;
- char *p = buf ;
- while (*url != ':' && *url != 0)
- *p++ = *url++ ;
- *p = 0 ;
- if (*url == 0)
- return false ;
- if (string_compare (buf,"file") == 0)
- {
- url++ ; // skip :
- if (*url == '/' && url[1] == '/') // rooted file?
- {
- url += 2 ;
- while (*url != '/' && *url != 0)
- *filename++ = *url++ ;
- *filename++ = '.' ;
- if (*url == 0)
- return false ;
- url++ ; // skip /
- }
- while (*url != '#' && *url != 0)
- *filename++ = *url++ ;
- *filename = 0 ;
- if (*url == '#') // any anchor
- {
- url++ ;
- while (*url != 0)
- *anchor++ = *url++ ;
- }
- *anchor = 0 ;
- return true ;
- }
- else
- return false ;
- }
-
-
- void Viewer::follow_hyperlink (char *filename, char *anchor)
- {
- if (filename[0] != 0) // change file?
- {
- if (current_context->next != NULL) // in the middle of the stack
- {
- Context *c, *next ;
- for (c = current_context->next ; c != NULL ; c = next)
- {
- next = c->next ;
- delete c ;
- }
- current_context->next = NULL ;
- context_stack = current_context ;
- }
- save_current_context() ;
- if (strcmp (filename,current_document) != 0)
- clear() ;
- display_file (filename) ;
- }
- if (anchor[0] != 0)
- scroll_to_anchor (anchor) ;
- }
-
-
- void Viewer::save_current_context()
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int block[9] ;
- block[0] = handle ;
- r.r[1] = (int)block ;
- if ((e = _kernel_swi (Wimp_GetWindowState, &r, &r)) != NULL)
- throw e ;
- current_context->x = block[5] ; // scx
- current_context->y = block[6] ; // scy
- }
-
-
- void Viewer::new_context()
- {
- Context *c = new Context ;
- c->next = NULL ;
- strcpy (c->filename, current_document) ;
- strcpy (c->root, document_root) ;
- if (context_stack != NULL)
- context_stack->next = c ;
- c->prev = context_stack ;
- context_stack = c ;
- current_context = c ;
- save_current_context() ;
- }
-
- void Viewer::back()
- {
- if (current_context->prev != NULL)
- {
- char path[256] ;
- Context *c ;
- current_context = current_context->prev ;
- c = current_context ;
- if (strcmp (c->filename,current_document) != 0)
- clear() ;
- sprintf (path, "%s.%s",c->root,c->filename) ;
- // ::print ("going back to %s",path) ;
- display_file (path,false) ;
- scroll_to (c->x, c->y) ;
- }
- }
-
- void Viewer::forward()
- {
- if (current_context->next != NULL)
- {
- char path[256] ;
- Context *c ;
- current_context = current_context->next ;
- c = current_context ;
- if (strcmp (c->filename,current_document) != 0)
- clear() ;
- sprintf (path, "%s.%s",c->root,c->filename) ;
- // ::print ("going forward to %s",path) ;
- display_file (path,false) ;
- scroll_to (c->x, c->y) ;
- }
- }
-
- void Viewer::home()
- {
- follow_hyperlink (home_document,"") ;
- }
-
- void Viewer::scroll_to(int x, int y)
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int block[9] ;
- block[0] = handle ;
- r.r[1] = (int)block ;
- if ((e = _kernel_swi (Wimp_GetWindowState, &r, &r)) != NULL)
- throw e ;
- do_open (block[1], block[2], block[3], block[4], x, y, block[7]) ;
- }
-
-
-
- void Viewer::push(int handle)
- {
- stack[sp++] = handle ;
- }
-
- int Viewer::pop()
- {
- return stack[--sp] ;
- }
-
-