fltk  1.3.5-source
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X.
  Fossies Dox: fltk-1.3.5-source.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Help_View.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Fl_Help_View widget routines.
5 //
6 // Copyright 1997-2010 by Easy Software Products.
7 // Image support by Matthias Melcher, Copyright 2000-2009.
8 //
9 // Buffer management (HV_Edit_Buffer) and more by AlbrechtS and others.
10 // Copyright 2011-2016 by Bill Spitzak and others.
11 //
12 // This library is free software. Distribution and use rights are outlined in
13 // the file "COPYING" which should have been included with this file. If this
14 // file is missing or damaged, see the license at:
15 //
16 // http://www.fltk.org/COPYING.php
17 //
18 // Please report all bugs and problems on the following page:
19 //
20 // http://www.fltk.org/str.php
21 //
22 // Contents:
23 //
24 // Fl_Help_View::add_block() - Add a text block to the list.
25 // Fl_Help_View::add_link() - Add a new link to the list.
26 // Fl_Help_View::add_target() - Add a new target to the list.
27 // Fl_Help_View::compare_targets() - Compare two targets.
28 // Fl_Help_View::do_align() - Compute the alignment for a line in
29 // a block.
30 // Fl_Help_View::draw() - Draw the Fl_Help_View widget.
31 // Fl_Help_View::format() - Format the help text.
32 // Fl_Help_View::format_table() - Format a table...
33 // Fl_Help_View::free_data() - Free memory used for the document.
34 // Fl_Help_View::get_align() - Get an alignment attribute.
35 // Fl_Help_View::get_attr() - Get an attribute value from the string.
36 // Fl_Help_View::get_color() - Get an alignment attribute.
37 // Fl_Help_View::handle() - Handle events in the widget.
38 // Fl_Help_View::Fl_Help_View() - Build a Fl_Help_View widget.
39 // Fl_Help_View::~Fl_Help_View() - Destroy a Fl_Help_View widget.
40 // Fl_Help_View::load() - Load the specified file.
41 // Fl_Help_View::resize() - Resize the help widget.
42 // Fl_Help_View::topline() - Set the top line to the named target.
43 // Fl_Help_View::topline() - Set the top line by number.
44 // Fl_Help_View::value() - Set the help text directly.
45 // scrollbar_callback() - A callback for the scrollbar.
46 //
47 
48 //
49 // Include necessary header files...
50 //
51 
52 #include <FL/Fl_Help_View.H>
53 #include <FL/Fl_Window.H>
54 #include <FL/Fl_Pixmap.H>
55 #include <FL/x.H>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <FL/fl_utf8.h>
59 #include <FL/filename.H> // fl_open_uri()
60 #include "flstring.h"
61 #include <ctype.h>
62 #include <errno.h>
63 #include <math.h>
64 
65 #if defined(WIN32) && ! defined(__CYGWIN__)
66 # include <io.h>
67 # include <direct.h>
68 #else
69 # include <unistd.h>
70 #endif // WIN32
71 
72 #define MAX_COLUMNS 200
73 
74 //
75 // Typedef the C API sort function type the only way I know how...
76 //
77 
78 extern "C"
79 {
80  typedef int (*compare_func_t)(const void *, const void *);
81 }
82 
83 
84 //
85 // Local functions...
86 //
87 
88 static int quote_char(const char *);
89 static void scrollbar_callback(Fl_Widget *s, void *);
90 static void hscrollbar_callback(Fl_Widget *s, void *);
91 
92 //
93 // global flag for image loading (see get_image).
94 //
95 
96 static char initial_load = 0;
97 
98 //
99 // Broken image...
100 //
101 
102 static const char * const broken_xpm[] =
103  {
104  "16 24 4 1",
105  "@ c #000000",
106  " c #ffffff",
107  "+ c none",
108  "x c #ff0000",
109  // pixels
110  "@@@@@@@+++++++++",
111  "@ @++++++++++",
112  "@ @+++++++++++",
113  "@ @++@++++++++",
114  "@ @@+++++++++",
115  "@ @+++@+++++",
116  "@ @++@@++++@",
117  "@ xxx @@ @++@@",
118  "@ xxx xx@@ @",
119  "@ xxx xxx @",
120  "@ xxxxxx @",
121  "@ xxxx @",
122  "@ xxxxxx @",
123  "@ xxx xxx @",
124  "@ xxx xxx @",
125  "@ xxx xxx @",
126  "@ @",
127  "@ @",
128  "@ @",
129  "@ @",
130  "@ @",
131  "@ @",
132  "@ @",
133  "@@@@@@@@@@@@@@@@",
134  NULL
135  };
136 
138 
139 //
140 // Simple margin stack for Fl_Help_View::format()...
141 //
142 
143 struct fl_margins {
144  int depth_;
145  int margins_[100];
146 
147  fl_margins() { clear(); }
148 
149  int clear() {
150 // puts("fl_margins::clear()");
151 
152  depth_ = 0;
153  return margins_[0] = 4;
154  }
155 
156  int current() { return margins_[depth_]; }
157 
158  int pop() {
159 // printf("fl_margins::pop(): depth_=%d, xx=%d\n", depth_,
160 // depth_ > 0 ? margins_[depth_ - 1] : 4);
161 
162  if (depth_ > 0) {
163  depth_ --;
164  return margins_[depth_];
165  } else return 4;
166  }
167 
168  int push(int indent) {
169  int xx;
170 
171  xx = margins_[depth_] + indent;
172 
173 // printf("fl_margins::push(indent=%d): depth_=%d, xx=%d\n", indent,
174 // depth_ + 1, xx);
175 
176  if (depth_ < 99) {
177  depth_ ++;
178  margins_[depth_] = xx;
179  }
180 
181  return xx;
182  }
183 };
184 
185 //
186 // All the stuff needed to implement text selection in Fl_Help_View
187 //
188 
189 /* matt:
190  * We are trying to keep binary compatibility with previous versions
191  * of FLTK. This means that we are limited to adding static variables
192  * only to not enlarge the Fl_Help_View class. Lucky for us, only one
193  * text can be selected system wide, so we can remember the selection
194  * in a single set of variables.
195  *
196  * Still to do:
197  * - &word; style characters mess up our count inside a word boundary
198  * - we can only select words, no individual characters
199  * - no dragging of the selection into another widget
200  * - selection must be cleared if another widget get focus!
201  * - write a comment for every new function
202  */
203 
204 /*
205 The following functions are also used to draw stuff and should be replaced with
206 local copies that are much faster when merely counting:
207 
208 fl_color(Fl_Color);
209 fl_rectf(int, int, int, int);
210 fl_push_clip(int, int, int, int);
211 fl_xyline(int, int, int);
212 fl_rect()
213 fl_line()
214 img->draw()
215 */
216 
217 // We don't put the offscreen buffer in the help view class because
218 // we'd need to include x.H in the header...
226 int Fl_Help_View::selected = 0;
228 int Fl_Help_View::mouse_x = 0;
229 int Fl_Help_View::mouse_y = 0;
234 
235 /*
236  * This function must be optimized for speed!
237  */
238 void Fl_Help_View::hv_draw(const char *t, int x, int y, int entity_extra_length)
239 {
240  if (selected && current_view==this && current_pos<selection_last && current_pos>=selection_first) {
241  Fl_Color c = fl_color();
243  int w = (int)fl_width(t);
244  if (current_pos+(int)strlen(t)<selection_last)
245  w += (int)fl_width(' ');
248  fl_draw(t, x, y);
249  fl_color(c);
250  } else {
251  fl_draw(t, x, y);
252  }
253  if (draw_mode) {
254  int w = (int)fl_width(t);
255  if (mouse_x>=x && mouse_x<x+w) {
257  int f = (int) current_pos;
258  int l = (int) (f+strlen(t)); // use 'quote_char' to calculate the true length of the HTML string
259  if (draw_mode==1) {
262  } else {
264  selection_drag_last = l + entity_extra_length;
265  }
266  }
267  }
268  }
269 }
270 
271 #define DEBUG_EDIT_BUFFER 0
272 
273 #if (DEBUG_EDIT_BUFFER > 1)
274 #define DEBUG_FUNCTION(L,F) \
275  printf("\n========\n [%d] --- %s\n========\n", L, F); \
276  fflush(stdout);
277 #else
278 #define DEBUG_FUNCTION(L,F)
279 #endif
280 
281 
282 /* ** Intentionally not Doxygen docs.
283  HelpView Edit Buffer management class.
284  <b>Internal use only.</b>
285 
286  This class is for internal use in this file. Its sole purpose is to
287  allow buffer management to avoid buffer overflows in stack variables
288  used to edit strings for formatting and drawing (STR #3275).
289 
290  This class will likely be superseded by an Fl_String or Fl_Buffer class
291  in a later FLTK release (1.4.x).
292 
293  Note: The buffer allocation and extension size (chunk size) must be
294  a power of 2, but this is deliberately never checked, because this
295  class is only used here with default values. Using extension sizes
296  that are not a power of 2 may result in unpredictable behavior.
297 */
298 
300 
301  int size_; // actually used text size w/o nul
302  int allocated_; // allocated buffer size
303  int extend_; // extend size (must be a power of 2)
304 
305  char *buf_; // internal buffer
306 
307 public:
308 
309  HV_Edit_Buffer (int alloc = 1024, int ext = 1024); // c'tor
310  ~HV_Edit_Buffer (); // d'tor
311 
312  char *c_str() { return buf_; }
313  void clear();
314  int size() { return size_; }
315  void check(int size);
316  const char *add(const char *text, int size = -1);
317  void add(char c);
318  void add(int ucs);
319 
320  int cmp(const char * str) { return !strcasecmp(buf_, str); }
321  int width() { return (int)fl_width(buf_); }
322 
323  char & operator[] (int idx) { return buf_[idx]; }
324  char operator[] (int idx) const { return buf_[idx]; }
325 
326 #if (DEBUG_EDIT_BUFFER)
327  void print(const char *text = "");
328 #endif
329 };
330 
331 /*
332  Edit buffer constructor.
333 */
335  int alloc,
336  int ext)
337 {
338  alloc = (alloc + ext-1) & (~(ext-1)); // round to chunk size
339 
340  size_ = 0;
341  allocated_ = alloc;
342  extend_ = ext;
343  buf_ = (char *)malloc(alloc);
344 }
345 
346 /*
347  Clears the edit buffer, but doesn't free the buffer.
348 */
350 {
351 
352  // DEBUG_FUNCTION(__LINE__,__FUNCTION__);
353 
354  size_ = 0;
355  buf_[0] = '\0';
356 }
357 
358 /*
359  Adds text to the buffer.
360 
361  \param[in] text text to be added
362  \param[in] size text size, default: -1 => strlen(text)
363  \returns new input text pointer, i.e. points beyond inserted text
364 */
365 const char *HV_Edit_Buffer::add(const char *text, int size) {
366 
367  if (size < 0) size = (int)strlen(text);
368  if (!size) return text;
369 
370  check(size);
371 
372 #if (DEBUG_EDIT_BUFFER > 1)
373  printf("HV_Edit_Buffer::add(text,%d), allocated=%d, size=%d\n",
375  fflush(stdout);
376 #endif
377 
378  memcpy(buf_+size_, text, size);
379  size_ += size;
380  buf_[size_] = '\0';
381 
382  return (text + size);
383 
384 } // add(const char *text, int size)
385 
386 /*
387  Adds one byte (character) to the buffer.
388 
389  \note It is possible to add partial UTF-8 sequences.
390 
391  \param[in] c byte (char) to be added
392 */
393 void HV_Edit_Buffer::add(char c) {
394 
395  check(1);
396 
397 #if (DEBUG_EDIT_BUFFER > 1)
398  printf("HV_Edit_Buffer::add(char = '%c'), allocated=%d, size=%d\n",
399  c, allocated_, size_+1);
400  fflush(stdout);
401 #endif
402 
403  buf_[size_++] = c;
404  buf_[size_] = '\0';
405 
406 } // add(char c)
407 
408 /*
409  Adds one Unicode character (int) to the buffer.
410 
411  The Unicode character \p ucs is converted to UTF-8 and appended to
412  the buffer.
413 
414  \param[in] ucs Unicode character (code point) to be added
415 */
416 void HV_Edit_Buffer::add(int ucs) {
417 
418  int len;
419  char cbuf[6];
420 
421  len = fl_utf8encode((unsigned int)ucs, cbuf);
422  if (len < 1) len = 1;
423  add(cbuf,len);
424 
425 } // add(int ucs)
426 
427 /*
428  Checks needed buffer size and reallocates the buffer if necessary.
429 
430  Tests if the given string \p size can be added to the string buffer.
431  An additional nul byte is also considered in the calculation.
432 
433  \p size must be >= 0.
434 
435  If the requested \p size doesn't fit in the allocated buffer size,
436  the buffer is extended.
437 
438  \param[in] size requested text size to be added (w/o trailing nul)
439 */
440 void HV_Edit_Buffer::check(int size) {
441 
442  if (size_ + size + 1 <= allocated_) return;
443 
444  int new_size = (allocated_ + size + extend_) & (~(extend_-1)); // round to chunk size
445 
446  buf_ = (char *)realloc(buf_, new_size);
447 
448 #if (DEBUG_EDIT_BUFFER)
449  printf("HV_Edit_Buffer::check(%d), allocated: %d ->%d\n",
450  size, allocated_, new_size);
451  fflush(stdout);
452 #endif
453 
454  allocated_ = new_size;
455 
456 } // HV_Edit_Buffer::check()
457 
458 
459 /*
460  The destructor frees the edit buffer.
461 */
463 
464  if (buf_) {
465 #if (DEBUG_EDIT_BUFFER)
466  printf("~HV_Edit_Buffer(): size = %d, allocated = %d\n",
467  size_, allocated_);
468  fflush(stdout);
469 #endif
470  free(buf_);
471  }
472 } // ~HV_Edit_Buffer()
473 
474 
475 /*
476  Prints the edit buffer (Debug only).
477 */
478 #if (DEBUG_EDIT_BUFFER)
479 void HV_Edit_Buffer::print(const char *text) {
480  printf("HV_Edit_Buffer::print(%s), allocated=%d, size=%d\n",
481  text, allocated_, size_);
482  printf(" \"%s\"\n", buf_ && size_ ? buf_ : "");
483  fflush(stdout);
484 } // print()
485 #endif
486 
488 Fl_Help_Block * // O - Pointer to new block
489 Fl_Help_View::add_block(const char *s, // I - Pointer to start of block text
490  int xx, // I - X position of block
491  int yy, // I - Y position of block
492  int ww, // I - Right margin of block
493  int hh, // I - Height of block
494  unsigned char border) // I - Draw border?
495 {
496  Fl_Help_Block *temp; // New block
497 
498 
499  // printf("add_block(s = %p, xx = %d, yy = %d, ww = %d, hh = %d, border = %d)\n",
500  // s, xx, yy, ww, hh, border);
501 
502  if (nblocks_ >= ablocks_)
503  {
504  ablocks_ += 16;
505 
506  if (ablocks_ == 16)
508  else
509  blocks_ = (Fl_Help_Block *)realloc(blocks_, sizeof(Fl_Help_Block) * ablocks_);
510  }
511 
512  temp = blocks_ + nblocks_;
513  memset(temp, 0, sizeof(Fl_Help_Block));
514  temp->start = s;
515  temp->end = s;
516  temp->x = xx;
517  temp->y = yy;
518  temp->w = ww;
519  temp->h = hh;
520  temp->border = border;
521  temp->bgcolor = bgcolor_;
522  nblocks_ ++;
523 
524  return (temp);
525 }
526 
527 
529 void Fl_Help_View::add_link(const char *n, // I - Name of link
530  int xx, // I - X position of link
531  int yy, // I - Y position of link
532  int ww, // I - Width of link text
533  int hh) // I - Height of link text
534 {
535  Fl_Help_Link *temp; // New link
536  char *target; // Pointer to target name
537 
538 
539  if (nlinks_ >= alinks_)
540  {
541  alinks_ += 16;
542 
543  if (alinks_ == 16)
545  else
546  links_ = (Fl_Help_Link *)realloc(links_, sizeof(Fl_Help_Link) * alinks_);
547  }
548 
549  temp = links_ + nlinks_;
550 
551  temp->x = xx;
552  temp->y = yy;
553  temp->w = xx + ww;
554  temp->h = yy + hh;
555 
556  strlcpy(temp->filename, n, sizeof(temp->filename));
557 
558  if ((target = strrchr(temp->filename, '#')) != NULL)
559  {
560  *target++ = '\0';
561  strlcpy(temp->name, target, sizeof(temp->name));
562  }
563  else
564  temp->name[0] = '\0';
565 
566  nlinks_ ++;
567 }
568 
569 
571 void Fl_Help_View::add_target(const char *n, // I - Name of target
572  int yy) // I - Y position of target
573 {
574  Fl_Help_Target *temp; // New target
575 
576 
577  if (ntargets_ >= atargets_)
578  {
579  atargets_ += 16;
580 
581  if (atargets_ == 16)
583  else
584  targets_ = (Fl_Help_Target *)realloc(targets_, sizeof(Fl_Help_Target) * atargets_);
585  }
586 
587  temp = targets_ + ntargets_;
588 
589  temp->y = yy;
590  strlcpy(temp->name, n, sizeof(temp->name));
591 
592  ntargets_ ++;
593 }
594 
596 int // O - Result of comparison
597 Fl_Help_View::compare_targets(const Fl_Help_Target *t0, // I - First target
598  const Fl_Help_Target *t1) // I - Second target
599 {
600  return (strcasecmp(t0->name, t1->name));
601 }
602 
604 int // O - New line
605 Fl_Help_View::do_align(Fl_Help_Block *block, // I - Block to add to
606  int line, // I - Current line
607  int xx, // I - Current X position
608  int a, // I - Current alignment
609  int &l) // IO - Starting link
610 {
611  int offset; // Alignment offset
612 
613 
614  switch (a)
615  {
616  case RIGHT : // Right align
617  offset = block->w - xx;
618  break;
619  case CENTER : // Center
620  offset = (block->w - xx) / 2;
621  break;
622  default : // Left align
623  offset = 0;
624  break;
625  }
626 
627  block->line[line] = block->x + offset;
628 
629  if (line < 31)
630  line ++;
631 
632  while (l < nlinks_)
633  {
634  links_[l].x += offset;
635  links_[l].w += offset;
636  l ++;
637  }
638 
639  return (line);
640 }
641 
643 void
645 {
646  int i; // Looping var
647  const Fl_Help_Block *block; // Pointer to current block
648  const char *ptr, // Pointer to text in block
649  *attrs; // Pointer to start of element attributes
650  HV_Edit_Buffer buf; // Text buffer
651  char attr[1024]; // Attribute buffer
652  int xx, yy, ww, hh; // Current positions and sizes
653  int line; // Current line
654  Fl_Font font;
655  Fl_Fontsize fsize; // Current font and size
656  Fl_Color fcolor; // current font color
657  int head, pre, // Flags for text
658  needspace; // Do we need whitespace?
659  Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
660  // Box to draw...
661  int underline, // Underline text?
662  xtra_ww; // Extra width for underlined space between words
663 
664  DEBUG_FUNCTION(__LINE__,__FUNCTION__);
665 
666  // Draw the scrollbar(s) and box first...
667  ww = w();
668  hh = h();
669  i = 0;
670 
671  draw_box(b, x(), y(), ww, hh, bgcolor_);
672 
673  if ( hscrollbar_.visible() || scrollbar_.visible() ) {
674  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
675  int hor_vis = hscrollbar_.visible();
676  int ver_vis = scrollbar_.visible();
677  // Scrollbar corner
678  int scorn_x = x() + ww - (ver_vis?scrollsize:0) - Fl::box_dw(b) + Fl::box_dx(b);
679  int scorn_y = y() + hh - (hor_vis?scrollsize:0) - Fl::box_dh(b) + Fl::box_dy(b);
680  if ( hor_vis ) {
681  if ( hscrollbar_.h() != scrollsize ) { // scrollsize changed?
682  hscrollbar_.resize(x(), scorn_y, scorn_x - x(), scrollsize);
683  init_sizes();
684  }
686  hh -= scrollsize;
687  }
688  if ( ver_vis ) {
689  if ( scrollbar_.w() != scrollsize ) { // scrollsize changed?
690  scrollbar_.resize(scorn_x, y(), scrollsize, scorn_y - y());
691  init_sizes();
692  }
694  ww -= scrollsize;
695  }
696  if ( hor_vis && ver_vis ) {
697  // Both scrollbars visible? Draw little gray box in corner
698  fl_color(FL_GRAY);
699  fl_rectf(scorn_x, scorn_y, scrollsize, scrollsize);
700  }
701  }
702 
703  if (!value_)
704  return;
705 
706  if (current_view == this && selected) {
709  }
710  current_pos = 0;
711 
712  // Clip the drawing to the inside of the box...
713  fl_push_clip(x() + Fl::box_dx(b), y() + Fl::box_dy(b),
714  ww - Fl::box_dw(b), hh - Fl::box_dh(b));
716 
717  // Draw all visible blocks...
718  for (i = 0, block = blocks_; i < nblocks_; i ++, block ++)
719  if ((block->y + block->h) >= topline_ && block->y < (topline_ + h()))
720  {
721  line = 0;
722  xx = block->line[line];
723  yy = block->y - topline_;
724  hh = 0;
725  pre = 0;
726  head = 0;
727  needspace = 0;
728  underline = 0;
729 
730  initfont(font, fsize, fcolor);
731  // byte length difference between html entity (encoded by &...;) and
732  // UTF-8 encoding of same character
733  int entity_extra_length = 0;
734  for (ptr = block->start, buf.clear(); ptr < block->end;)
735  {
736  if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0)
737  {
738  if (!head && !pre)
739  {
740  // Check width...
741  ww = buf.width();
742 
743  if (needspace && xx > block->x)
744  xx += (int)fl_width(' ');
745 
746  if ((xx + ww) > block->w)
747  {
748  if (line < 31)
749  line ++;
750  xx = block->line[line];
751  yy += hh;
752  hh = 0;
753  }
754 
755  hv_draw(buf.c_str(), xx + x() - leftline_, yy + y(), entity_extra_length);
756  buf.clear();
757  entity_extra_length = 0;
758  if (underline) {
759  xtra_ww = isspace((*ptr)&255)?(int)fl_width(' '):0;
760  fl_xyline(xx + x() - leftline_, yy + y() + 1,
761  xx + x() - leftline_ + ww + xtra_ww);
762  }
763  current_pos = (int) (ptr-value_);
764 
765  xx += ww;
766  if ((fsize + 2) > hh)
767  hh = fsize + 2;
768 
769  needspace = 0;
770  }
771  else if (pre)
772  {
773  while (isspace((*ptr)&255))
774  {
775  if (*ptr == '\n')
776  {
777  hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
778  if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
779  xx + x() - leftline_ + buf.width());
780  buf.clear();
781  current_pos = (int) (ptr-value_);
782  if (line < 31)
783  line ++;
784  xx = block->line[line];
785  yy += hh;
786  hh = fsize + 2;
787  }
788  else if (*ptr == '\t')
789  {
790  // Do tabs every 8 columns...
791  buf.add(' '); // add at least one space
792  while (buf.size() & 7)
793  buf.add(' ');
794  }
795  else {
796  buf.add(' ');
797  }
798  if ((fsize + 2) > hh)
799  hh = fsize + 2;
800 
801  ptr ++;
802  }
803 
804  if (buf.size() > 0)
805  {
806  hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
807  ww = buf.width();
808  buf.clear();
809  if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
810  xx + x() - leftline_ + ww);
811  xx += ww;
812  current_pos = (int) (ptr-value_);
813  }
814 
815  needspace = 0;
816  }
817  else
818  {
819  buf.clear();
820 
821  while (isspace((*ptr)&255))
822  ptr ++;
823  current_pos = (int) (ptr-value_);
824  }
825  }
826 
827  if (*ptr == '<')
828  {
829  ptr ++;
830 
831  if (strncmp(ptr, "!--", 3) == 0)
832  {
833  // Comment...
834  ptr += 3;
835  if ((ptr = strstr(ptr, "-->")) != NULL)
836  {
837  ptr += 3;
838  continue;
839  }
840  else
841  break;
842  }
843 
844  while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
845  buf.add(*ptr++);
846 
847  attrs = ptr;
848  while (*ptr && *ptr != '>')
849  ptr ++;
850 
851  if (*ptr == '>')
852  ptr ++;
853 
854  // end of command reached, set the supposed start of printed eord here
855  current_pos = (int) (ptr-value_);
856  if (buf.cmp("HEAD"))
857  head = 1;
858  else if (buf.cmp("BR"))
859  {
860  if (line < 31)
861  line ++;
862  xx = block->line[line];
863  yy += hh;
864  hh = 0;
865  }
866  else if (buf.cmp("HR"))
867  {
868  fl_line(block->x + x(), yy + y(), block->w + x(),
869  yy + y());
870 
871  if (line < 31)
872  line ++;
873  xx = block->line[line];
874  yy += 2 * fsize; //hh;
875  hh = 0;
876  }
877  else if (buf.cmp("CENTER") ||
878  buf.cmp("P") ||
879  buf.cmp("H1") ||
880  buf.cmp("H2") ||
881  buf.cmp("H3") ||
882  buf.cmp("H4") ||
883  buf.cmp("H5") ||
884  buf.cmp("H6") ||
885  buf.cmp("UL") ||
886  buf.cmp("OL") ||
887  buf.cmp("DL") ||
888  buf.cmp("LI") ||
889  buf.cmp("DD") ||
890  buf.cmp("DT") ||
891  buf.cmp("PRE"))
892  {
893  if (tolower(buf[0]) == 'h')
894  {
895  font = FL_HELVETICA_BOLD;
896  fsize = textsize_ + '7' - buf[1];
897  }
898  else if (buf.cmp("DT"))
899  {
900  font = textfont_ | FL_ITALIC;
901  fsize = textsize_;
902  }
903  else if (buf.cmp("PRE"))
904  {
905  font = FL_COURIER;
906  fsize = textsize_;
907  pre = 1;
908  }
909 
910  if (buf.cmp("LI"))
911  {
912  // draw bullet (&bull;) Unicode: U+2022, UTF-8 (hex): e2 80 a2
913  unsigned char bullet[4] = { 0xe2, 0x80, 0xa2, 0x00 };
914  hv_draw((char *)bullet, xx - fsize + x() - leftline_, yy + y());
915  }
916 
917  pushfont(font, fsize);
918  buf.clear();
919  }
920  else if (buf.cmp("A") &&
921  get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
922  {
924  underline = 1;
925  }
926  else if (buf.cmp("/A"))
927  {
929  underline = 0;
930  }
931  else if (buf.cmp("FONT"))
932  {
933  if (get_attr(attrs, "COLOR", attr, sizeof(attr)) != NULL) {
935  }
936 
937  if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) {
938  if (!strncasecmp(attr, "helvetica", 9) ||
939  !strncasecmp(attr, "arial", 5) ||
940  !strncasecmp(attr, "sans", 4)) font = FL_HELVETICA;
941  else if (!strncasecmp(attr, "times", 5) ||
942  !strncasecmp(attr, "serif", 5)) font = FL_TIMES;
943  else if (!strncasecmp(attr, "symbol", 6)) font = FL_SYMBOL;
944  else font = FL_COURIER;
945  }
946 
947  if (get_attr(attrs, "SIZE", attr, sizeof(attr)) != NULL) {
948  if (isdigit(attr[0] & 255)) {
949  // Absolute size
950  fsize = (int)(textsize_ * pow(1.2, atof(attr) - 3.0));
951  } else {
952  // Relative size
953  fsize = (int)(fsize * pow(1.2, atof(attr) - 3.0));
954  }
955  }
956 
957  pushfont(font, fsize);
958  }
959  else if (buf.cmp("/FONT"))
960  {
961  popfont(font, fsize, textcolor_);
962  }
963  else if (buf.cmp("U"))
964  underline = 1;
965  else if (buf.cmp("/U"))
966  underline = 0;
967  else if (buf.cmp("B") ||
968  buf.cmp("STRONG"))
969  pushfont(font |= FL_BOLD, fsize);
970  else if (buf.cmp("TD") ||
971  buf.cmp("TH"))
972  {
973  int tx, ty, tw, th;
974 
975  if (tolower(buf[1]) == 'h')
976  pushfont(font |= FL_BOLD, fsize);
977  else
978  pushfont(font = textfont_, fsize);
979 
980  tx = block->x - 4 - leftline_;
981  ty = block->y - topline_ - fsize - 3;
982  tw = block->w - block->x + 7;
983  th = block->h + fsize - 5;
984 
985  if (tx < 0)
986  {
987  tw += tx;
988  tx = 0;
989  }
990 
991  if (ty < 0)
992  {
993  th += ty;
994  ty = 0;
995  }
996 
997  tx += x();
998  ty += y();
999 
1000  if (block->bgcolor != bgcolor_)
1001  {
1002  fl_color(block->bgcolor);
1003  fl_rectf(tx, ty, tw, th);
1005  }
1006 
1007  if (block->border)
1008  fl_rect(tx, ty, tw, th);
1009  }
1010  else if (buf.cmp("I") ||
1011  buf.cmp("EM"))
1012  pushfont(font |= FL_ITALIC, fsize);
1013  else if (buf.cmp("CODE") ||
1014  buf.cmp("TT"))
1015  pushfont(font = FL_COURIER, fsize);
1016  else if (buf.cmp("KBD"))
1017  pushfont(font = FL_COURIER_BOLD, fsize);
1018  else if (buf.cmp("VAR"))
1019  pushfont(font = FL_COURIER_ITALIC, fsize);
1020  else if (buf.cmp("/HEAD"))
1021  head = 0;
1022  else if (buf.cmp("/H1") ||
1023  buf.cmp("/H2") ||
1024  buf.cmp("/H3") ||
1025  buf.cmp("/H4") ||
1026  buf.cmp("/H5") ||
1027  buf.cmp("/H6") ||
1028  buf.cmp("/B") ||
1029  buf.cmp("/STRONG") ||
1030  buf.cmp("/I") ||
1031  buf.cmp("/EM") ||
1032  buf.cmp("/CODE") ||
1033  buf.cmp("/TT") ||
1034  buf.cmp("/KBD") ||
1035  buf.cmp("/VAR"))
1036  popfont(font, fsize, fcolor);
1037  else if (buf.cmp("/PRE"))
1038  {
1039  popfont(font, fsize, fcolor);
1040  pre = 0;
1041  }
1042  else if (buf.cmp("IMG"))
1043  {
1044  Fl_Shared_Image *img = 0;
1045  int width, height;
1046  char wattr[8], hattr[8];
1047 
1048 
1049  get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
1050  get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
1051  width = get_length(wattr);
1052  height = get_length(hattr);
1053 
1054  if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
1055  img = get_image(attr, width, height);
1056  if (!width) width = img->w();
1057  if (!height) height = img->h();
1058  }
1059 
1060  if (!width || !height) {
1061  if (get_attr(attrs, "ALT", attr, sizeof(attr)) == NULL) {
1062  strcpy(attr, "IMG");
1063  }
1064  }
1065 
1066  ww = width;
1067 
1068  if (needspace && xx > block->x)
1069  xx += (int)fl_width(' ');
1070 
1071  if ((xx + ww) > block->w)
1072  {
1073  if (line < 31)
1074  line ++;
1075 
1076  xx = block->line[line];
1077  yy += hh;
1078  hh = 0;
1079  }
1080 
1081  if (img) {
1082  img->draw(xx + x() - leftline_,
1083  yy + y() - fl_height() + fl_descent() + 2);
1084  }
1085 
1086  xx += ww;
1087  if ((height + 2) > hh)
1088  hh = height + 2;
1089 
1090  needspace = 0;
1091  }
1092  buf.clear();
1093  }
1094  else if (*ptr == '\n' && pre)
1095  {
1096  hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
1097  buf.clear();
1098 
1099  if (line < 31)
1100  line ++;
1101  xx = block->line[line];
1102  yy += hh;
1103  hh = fsize + 2;
1104  needspace = 0;
1105 
1106  ptr ++;
1107  current_pos = (int) (ptr-value_);
1108  }
1109  else if (isspace((*ptr)&255))
1110  {
1111  if (pre)
1112  {
1113  if (*ptr == ' ')
1114  buf.add(' ');
1115  else
1116  {
1117  // Do tabs every 8 columns...
1118  buf.add(' '); // at least one space
1119  while (buf.size() & 7)
1120  buf.add(' ');
1121  }
1122  }
1123 
1124  ptr ++;
1125  if (!pre) current_pos = (int) (ptr-value_);
1126  needspace = 1;
1127  }
1128  else if (*ptr == '&') // process html entity
1129  {
1130  ptr ++;
1131 
1132  int qch = quote_char(ptr);
1133 
1134  if (qch < 0)
1135  buf.add('&');
1136  else {
1137  int utf8l = buf.size();
1138  buf.add(qch);
1139  utf8l = buf.size() - utf8l; // length of added UTF-8 text
1140  const char *oldptr = ptr;
1141  ptr = strchr(ptr, ';') + 1;
1142  entity_extra_length += ptr - (oldptr-1) - utf8l; // extra length between html entity and UTF-8
1143  }
1144 
1145  if ((fsize + 2) > hh)
1146  hh = fsize + 2;
1147  }
1148  else
1149  {
1150  buf.add(*ptr++);
1151 
1152  if ((fsize + 2) > hh)
1153  hh = fsize + 2;
1154  }
1155  }
1156 
1157  if (buf.size() > 0 && !pre && !head)
1158  {
1159  ww = buf.width();
1160 
1161  if (needspace && xx > block->x)
1162  xx += (int)fl_width(' ');
1163 
1164  if ((xx + ww) > block->w)
1165  {
1166  if (line < 31)
1167  line ++;
1168  xx = block->line[line];
1169  yy += hh;
1170  hh = 0;
1171  }
1172  }
1173 
1174  if (buf.size() > 0 && !head)
1175  {
1176  hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
1177  if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
1178  xx + x() - leftline_ + ww);
1179  current_pos = (int) (ptr-value_);
1180  }
1181  }
1182 
1183  fl_pop_clip();
1184 } // draw()
1185 
1186 
1187 
1192 int // O - Matching position or -1 if not found
1193 Fl_Help_View::find(const char *s, // I - String to find
1194  int p) // I - Starting position
1195 {
1196  int i, // Looping var
1197  c; // Current character
1198  Fl_Help_Block *b; // Current block
1199  const char *bp, // Block matching pointer
1200  *bs, // Start of current comparison
1201  *sp; // Search string pointer
1202 
1203 
1204  DEBUG_FUNCTION(__LINE__,__FUNCTION__);
1205 
1206  // Range check input and value...
1207  if (!s || !value_) return -1;
1208 
1209  if (p < 0 || p >= (int)strlen(value_)) p = 0;
1210  else if (p > 0) p ++;
1211 
1212  // Look for the string...
1213  for (i = nblocks_, b = blocks_; i > 0; i --, b ++) {
1214  if (b->end < (value_ + p))
1215  continue;
1216 
1217  if (b->start < (value_ + p)) bp = value_ + p;
1218  else bp = b->start;
1219 
1220  for (sp = s, bs = bp; *sp && *bp && bp < b->end; bp ++) {
1221  if (*bp == '<') {
1222  // skip to end of element...
1223  while (*bp && bp < b->end && *bp != '>') bp ++;
1224  continue;
1225  } else if (*bp == '&') {
1226  // decode HTML entity...
1227  if ((c = quote_char(bp + 1)) < 0) c = '&'; // *FIXME* UTF-8, see below
1228  else bp = strchr(bp + 1, ';') + 1;
1229  } else c = *bp;
1230 
1231  // *FIXME* *UTF-8* (A.S. 02/14/2016)
1232  // At this point c may be an arbitrary Unicode Code Point corresponding
1233  // to a quoted character (see above), i.e. it _can_ be a multi byte
1234  // UTF-8 sequence and must be compared with the corresponding
1235  // multi byte string in (*sp)...
1236  // For instance: "&euro;" == 0x20ac -> 0xe2 0x82 0xac (UTF-8: 3 bytes).
1237  // Hint: use fl_utf8encode() [see below]
1238 
1239  if (tolower(*sp) == tolower(c)) sp ++;
1240  else {
1241  // No match, so reset to start of search...
1242  sp = s;
1243  bs ++;
1244  bp = bs;
1245  }
1246  }
1247 
1248  if (!*sp) {
1249  // Found a match!
1250  topline(b->y - b->h);
1251  return (int) (b->end - value_);
1252  }
1253  }
1254 
1255  // No match!
1256  return (-1);
1257 }
1258 
1261  int i; // Looping var
1262  int done; // Are we done yet?
1263  Fl_Help_Block *block, // Current block
1264  *cell; // Current table cell
1265  int cells[MAX_COLUMNS],
1266  // Cells in the current row...
1267  row; // Current table row (block number)
1268  const char *ptr, // Pointer into block
1269  *start, // Pointer to start of element
1270  *attrs; // Pointer to start of element attributes
1271  HV_Edit_Buffer buf; // Text buffer
1272  char attr[1024], // Attribute buffer
1273  wattr[1024], // Width attribute buffer
1274  hattr[1024], // Height attribute buffer
1275  linkdest[1024]; // Link destination
1276  int xx, yy, ww, hh; // Size of current text fragment
1277  int line; // Current line in block
1278  int links; // Links for current line
1279  Fl_Font font;
1280  Fl_Fontsize fsize; // Current font and size
1281  Fl_Color fcolor; // Current font color
1282  unsigned char border; // Draw border?
1283  int talign, // Current alignment
1284  newalign, // New alignment
1285  head, // In the <HEAD> section?
1286  pre, // <PRE> text?
1287  needspace; // Do we need whitespace?
1288  int table_width, // Width of table
1289  table_offset; // Offset of table
1290  int column, // Current table column number
1291  columns[MAX_COLUMNS];
1292  // Column widths
1293  Fl_Color tc, rc; // Table/row background color
1294  Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
1295  // Box to draw...
1296  fl_margins margins; // Left margin stack...
1297 
1298  DEBUG_FUNCTION(__LINE__,__FUNCTION__);
1299 
1300  // Reset document width...
1301  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
1302  hsize_ = w() - scrollsize - Fl::box_dw(b);
1303 
1304  done = 0;
1305  while (!done)
1306  {
1307  // Reset state variables...
1308  done = 1;
1309  nblocks_ = 0;
1310  nlinks_ = 0;
1311  ntargets_ = 0;
1312  size_ = 0;
1313  bgcolor_ = color();
1314  textcolor_ = textcolor();
1316 
1317  tc = rc = bgcolor_;
1318 
1319  strcpy(title_, "Untitled");
1320 
1321  if (!value_)
1322  return;
1323 
1324  // Setup for formatting...
1325  initfont(font, fsize, fcolor);
1326 
1327  line = 0;
1328  links = 0;
1329  xx = margins.clear();
1330  yy = fsize + 2;
1331  ww = 0;
1332  column = 0;
1333  border = 0;
1334  hh = 0;
1335  block = add_block(value_, xx, yy, hsize_, 0);
1336  row = 0;
1337  head = 0;
1338  pre = 0;
1339  talign = LEFT;
1340  newalign = LEFT;
1341  needspace = 0;
1342  linkdest[0] = '\0';
1343  table_offset = 0;
1344 
1345  // Html text character loop
1346  for (ptr = value_, buf.clear(); *ptr;)
1347  {
1348  // End of word?
1349  if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0)
1350  {
1351  // Get width of word parsed so far...
1352  ww = buf.width();
1353 
1354  if (!head && !pre)
1355  {
1356  // Check width...
1357  if (ww > hsize_) {
1358  hsize_ = ww;
1359  done = 0;
1360  break;
1361  }
1362 
1363  if (needspace && xx > block->x)
1364  ww += (int)fl_width(' ');
1365 
1366  // printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n",
1367  // line, xx, ww, block->x, block->w);
1368 
1369  if ((xx + ww) > block->w)
1370  {
1371  line = do_align(block, line, xx, newalign, links);
1372  xx = block->x;
1373  yy += hh;
1374  block->h += hh;
1375  hh = 0;
1376  }
1377 
1378  if (linkdest[0])
1379  add_link(linkdest, xx, yy - fsize, ww, fsize);
1380 
1381  xx += ww;
1382  if ((fsize + 2) > hh)
1383  hh = fsize + 2;
1384 
1385  needspace = 0;
1386  }
1387  else if (pre)
1388  {
1389  // Add a link as needed...
1390  if (linkdest[0])
1391  add_link(linkdest, xx, yy - hh, ww, hh);
1392 
1393  xx += ww;
1394  if ((fsize + 2) > hh)
1395  hh = fsize + 2;
1396 
1397  // Handle preformatted text...
1398  while (isspace((*ptr)&255))
1399  {
1400  if (*ptr == '\n')
1401  {
1402  if (xx > hsize_) break;
1403 
1404  line = do_align(block, line, xx, newalign, links);
1405  xx = block->x;
1406  yy += hh;
1407  block->h += hh;
1408  hh = fsize + 2;
1409  }
1410  else
1411  xx += (int)fl_width(' ');
1412 
1413  if ((fsize + 2) > hh)
1414  hh = fsize + 2;
1415 
1416  ptr ++;
1417  }
1418 
1419  if (xx > hsize_) {
1420  hsize_ = xx;
1421  done = 0;
1422  break;
1423  }
1424 
1425  needspace = 0;
1426  }
1427  else
1428  {
1429  // Handle normal text or stuff in the <HEAD> section...
1430  while (isspace((*ptr)&255))
1431  ptr ++;
1432  }
1433 
1434  buf.clear();
1435  }
1436 
1437  if (*ptr == '<')
1438  {
1439  // Handle html tags..
1440  start = ptr;
1441  ptr ++;
1442 
1443  if (strncmp(ptr, "!--", 3) == 0)
1444  {
1445  // Comment...
1446  ptr += 3;
1447  if ((ptr = strstr(ptr, "-->")) != NULL)
1448  {
1449  ptr += 3;
1450  continue;
1451  }
1452  else
1453  break;
1454  }
1455 
1456  while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
1457  buf.add(*ptr++);
1458 
1459  attrs = ptr;
1460  while (*ptr && *ptr != '>')
1461  ptr ++;
1462 
1463  if (*ptr == '>')
1464  ptr ++;
1465 
1466  if (buf.cmp("HEAD"))
1467  head = 1;
1468  else if (buf.cmp("/HEAD"))
1469  head = 0;
1470  else if (buf.cmp("TITLE"))
1471  {
1472  // Copy the title in the document...
1473  char *st;
1474  for (st = title_;
1475  *ptr != '<' && *ptr && st < (title_ + sizeof(title_) - 1);
1476  *st++ = *ptr++) {/*empty*/}
1477 
1478  *st = '\0';
1479  buf.clear();
1480  }
1481  else if (buf.cmp("A"))
1482  {
1483  if (get_attr(attrs, "NAME", attr, sizeof(attr)) != NULL)
1484  add_target(attr, yy - fsize - 2);
1485 
1486  if (get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
1487  strlcpy(linkdest, attr, sizeof(linkdest));
1488  }
1489  else if (buf.cmp("/A"))
1490  linkdest[0] = '\0';
1491  else if (buf.cmp("BODY"))
1492  {
1493  bgcolor_ = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)),
1494  color());
1495  textcolor_ = get_color(get_attr(attrs, "TEXT", attr, sizeof(attr)),
1496  textcolor());
1497  linkcolor_ = get_color(get_attr(attrs, "LINK", attr, sizeof(attr)),
1498  fl_contrast(FL_BLUE, color()));
1499  }
1500  else if (buf.cmp("BR"))
1501  {
1502  line = do_align(block, line, xx, newalign, links);
1503  xx = block->x;
1504  block->h += hh;
1505  yy += hh;
1506  hh = 0;
1507  }
1508  else if (buf.cmp("CENTER") ||
1509  buf.cmp("P") ||
1510  buf.cmp("H1") ||
1511  buf.cmp("H2") ||
1512  buf.cmp("H3") ||
1513  buf.cmp("H4") ||
1514  buf.cmp("H5") ||
1515  buf.cmp("H6") ||
1516  buf.cmp("UL") ||
1517  buf.cmp("OL") ||
1518  buf.cmp("DL") ||
1519  buf.cmp("LI") ||
1520  buf.cmp("DD") ||
1521  buf.cmp("DT") ||
1522  buf.cmp("HR") ||
1523  buf.cmp("PRE") ||
1524  buf.cmp("TABLE"))
1525  {
1526  block->end = start;
1527  line = do_align(block, line, xx, newalign, links);
1528  newalign = buf.cmp("CENTER") ? CENTER : LEFT;
1529  xx = block->x;
1530  block->h += hh;
1531 
1532  if (buf.cmp("UL") ||
1533  buf.cmp("OL") ||
1534  buf.cmp("DL"))
1535  {
1536  block->h += fsize + 2;
1537  xx = margins.push(4 * fsize);
1538  }
1539  else if (buf.cmp("TABLE"))
1540  {
1541  if (get_attr(attrs, "BORDER", attr, sizeof(attr)))
1542  border = (uchar)atoi(attr);
1543  else
1544  border = 0;
1545 
1546  tc = rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), bgcolor_);
1547 
1548  block->h += fsize + 2;
1549 
1550  format_table(&table_width, columns, start);
1551 
1552  if ((xx + table_width) > hsize_) {
1553 #ifdef DEBUG
1554  printf("xx=%d, table_width=%d, hsize_=%d\n", xx, table_width,
1555  hsize_);
1556 #endif // DEBUG
1557  hsize_ = xx + table_width;
1558  done = 0;
1559  break;
1560  }
1561 
1562  switch (get_align(attrs, talign))
1563  {
1564  default :
1565  table_offset = 0;
1566  break;
1567 
1568  case CENTER :
1569  table_offset = (hsize_ - table_width) / 2 - textsize_;
1570  break;
1571 
1572  case RIGHT :
1573  table_offset = hsize_ - table_width - textsize_;
1574  break;
1575  }
1576 
1577  column = 0;
1578  }
1579 
1580  if (tolower(buf[0]) == 'h' && isdigit(buf[1]))
1581  {
1582  font = FL_HELVETICA_BOLD;
1583  fsize = textsize_ + '7' - buf[1];
1584  }
1585  else if (buf.cmp("DT"))
1586  {
1587  font = textfont_ | FL_ITALIC;
1588  fsize = textsize_;
1589  }
1590  else if (buf.cmp("PRE"))
1591  {
1592  font = FL_COURIER;
1593  fsize = textsize_;
1594  pre = 1;
1595  }
1596  else
1597  {
1598  font = textfont_;
1599  fsize = textsize_;
1600  }
1601 
1602  pushfont(font, fsize);
1603 
1604  yy = block->y + block->h;
1605  hh = 0;
1606 
1607  if ((tolower(buf[0]) == 'h' && isdigit(buf[1])) ||
1608  buf.cmp("DD") ||
1609  buf.cmp("DT") ||
1610  buf.cmp("P"))
1611  yy += fsize + 2;
1612  else if (buf.cmp("HR"))
1613  {
1614  hh += 2 * fsize;
1615  yy += fsize;
1616  }
1617 
1618  if (row)
1619  block = add_block(start, xx, yy, block->w, 0);
1620  else
1621  block = add_block(start, xx, yy, hsize_, 0);
1622 
1623  needspace = 0;
1624  line = 0;
1625 
1626  if (buf.cmp("CENTER"))
1627  newalign = talign = CENTER;
1628  else
1629  newalign = get_align(attrs, talign);
1630  }
1631  else if (buf.cmp("/CENTER") ||
1632  buf.cmp("/P") ||
1633  buf.cmp("/H1") ||
1634  buf.cmp("/H2") ||
1635  buf.cmp("/H3") ||
1636  buf.cmp("/H4") ||
1637  buf.cmp("/H5") ||
1638  buf.cmp("/H6") ||
1639  buf.cmp("/PRE") ||
1640  buf.cmp("/UL") ||
1641  buf.cmp("/OL") ||
1642  buf.cmp("/DL") ||
1643  buf.cmp("/TABLE"))
1644  {
1645  line = do_align(block, line, xx, newalign, links);
1646  xx = block->x;
1647  block->end = ptr;
1648 
1649  if (buf.cmp("/UL") ||
1650  buf.cmp("/OL") ||
1651  buf.cmp("/DL"))
1652  {
1653  xx = margins.pop();
1654  block->h += fsize + 2;
1655  }
1656  else if (buf.cmp("/TABLE"))
1657  {
1658  block->h += fsize + 2;
1659  xx = margins.current();
1660  }
1661  else if (buf.cmp("/PRE"))
1662  {
1663  pre = 0;
1664  hh = 0;
1665  }
1666  else if (buf.cmp("/CENTER"))
1667  talign = LEFT;
1668 
1669  popfont(font, fsize, fcolor);
1670 
1671  //#if defined(__GNUC__)
1672  //#warning FIXME this isspace & 255 test will probably not work on a utf8 stream... And we use it everywhere!
1673  //#endif /*__GNUC__*/
1674  while (isspace((*ptr)&255))
1675  ptr ++;
1676 
1677  block->h += hh;
1678  yy += hh;
1679 
1680  if (tolower(buf[2]) == 'l')
1681  yy += fsize + 2;
1682 
1683  if (row)
1684  block = add_block(ptr, xx, yy, block->w, 0);
1685  else
1686  block = add_block(ptr, xx, yy, hsize_, 0);
1687 
1688  needspace = 0;
1689  hh = 0;
1690  line = 0;
1691  newalign = talign;
1692  }
1693  else if (buf.cmp("TR"))
1694  {
1695  block->end = start;
1696  line = do_align(block, line, xx, newalign, links);
1697  xx = block->x;
1698  block->h += hh;
1699 
1700  if (row)
1701  {
1702  yy = blocks_[row].y + blocks_[row].h;
1703 
1704  for (cell = blocks_ + row + 1; cell <= block; cell ++)
1705  if ((cell->y + cell->h) > yy)
1706  yy = cell->y + cell->h;
1707 
1708  block = blocks_ + row;
1709 
1710  block->h = yy - block->y + 2;
1711 
1712  for (i = 0; i < column; i ++)
1713  if (cells[i])
1714  {
1715  cell = blocks_ + cells[i];
1716  cell->h = block->h;
1717  }
1718  }
1719 
1720  memset(cells, 0, sizeof(cells));
1721 
1722  yy = block->y + block->h - 4;
1723  hh = 0;
1724  block = add_block(start, xx, yy, hsize_, 0);
1725  row = (int) (block - blocks_);
1726  needspace = 0;
1727  column = 0;
1728  line = 0;
1729 
1730  rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), tc);
1731  }
1732  else if (buf.cmp("/TR") && row)
1733  {
1734  line = do_align(block, line, xx, newalign, links);
1735  block->end = start;
1736  block->h += hh;
1737  talign = LEFT;
1738 
1739  xx = blocks_[row].x;
1740  yy = blocks_[row].y + blocks_[row].h;
1741 
1742  for (cell = blocks_ + row + 1; cell <= block; cell ++)
1743  if ((cell->y + cell->h) > yy)
1744  yy = cell->y + cell->h;
1745 
1746  block = blocks_ + row;
1747 
1748  block->h = yy - block->y + 2;
1749 
1750  for (i = 0; i < column; i ++)
1751  if (cells[i])
1752  {
1753  cell = blocks_ + cells[i];
1754  cell->h = block->h;
1755  }
1756 
1757  yy = block->y + block->h /*- 4*/;
1758  block = add_block(start, xx, yy, hsize_, 0);
1759  needspace = 0;
1760  row = 0;
1761  line = 0;
1762  }
1763  else if ((buf.cmp("TD") ||
1764  buf.cmp("TH")) && row)
1765  {
1766  int colspan; // COLSPAN attribute
1767 
1768 
1769  line = do_align(block, line, xx, newalign, links);
1770  block->end = start;
1771  block->h += hh;
1772 
1773  if (buf.cmp("TH"))
1774  font = textfont_ | FL_BOLD;
1775  else
1776  font = textfont_;
1777 
1778  fsize = textsize_;
1779 
1780  xx = blocks_[row].x + fsize + 3 + table_offset;
1781  for (i = 0; i < column; i ++)
1782  xx += columns[i] + 6;
1783 
1784  margins.push(xx - margins.current());
1785 
1786  if (get_attr(attrs, "COLSPAN", attr, sizeof(attr)) != NULL)
1787  colspan = atoi(attr);
1788  else
1789  colspan = 1;
1790 
1791  for (i = 0, ww = -6; i < colspan; i ++)
1792  ww += columns[column + i] + 6;
1793 
1794  if (block->end == block->start && nblocks_ > 1)
1795  {
1796  nblocks_ --;
1797  block --;
1798  }
1799 
1800  pushfont(font, fsize);
1801 
1802  yy = blocks_[row].y;
1803  hh = 0;
1804  block = add_block(start, xx, yy, xx + ww, 0, border);
1805  needspace = 0;
1806  line = 0;
1807  newalign = get_align(attrs, tolower(buf[1]) == 'h' ? CENTER : LEFT);
1808  talign = newalign;
1809 
1810  cells[column] = (int) (block - blocks_);
1811 
1812  column += colspan;
1813 
1814  block->bgcolor = get_color(get_attr(attrs, "BGCOLOR", attr,
1815  sizeof(attr)), rc);
1816  }
1817  else if ((buf.cmp("/TD") ||
1818  buf.cmp("/TH")) && row)
1819  {
1820  line = do_align(block, line, xx, newalign, links);
1821  popfont(font, fsize, fcolor);
1822  xx = margins.pop();
1823  talign = LEFT;
1824  }
1825  else if (buf.cmp("FONT"))
1826  {
1827  if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) {
1828  if (!strncasecmp(attr, "helvetica", 9) ||
1829  !strncasecmp(attr, "arial", 5) ||
1830  !strncasecmp(attr, "sans", 4)) font = FL_HELVETICA;
1831  else if (!strncasecmp(attr, "times", 5) ||
1832  !strncasecmp(attr, "serif", 5)) font = FL_TIMES;
1833  else if (!strncasecmp(attr, "symbol", 6)) font = FL_SYMBOL;
1834  else font = FL_COURIER;
1835  }
1836 
1837  if (get_attr(attrs, "SIZE", attr, sizeof(attr)) != NULL) {
1838  if (isdigit(attr[0] & 255)) {
1839  // Absolute size
1840  fsize = (int)(textsize_ * pow(1.2, atoi(attr) - 3.0));
1841  } else {
1842  // Relative size
1843  fsize = (int)(fsize * pow(1.2, atoi(attr)));
1844  }
1845  }
1846 
1847  pushfont(font, fsize);
1848  }
1849  else if (buf.cmp("/FONT"))
1850  popfont(font, fsize, fcolor);
1851  else if (buf.cmp("B") ||
1852  buf.cmp("STRONG"))
1853  pushfont(font |= FL_BOLD, fsize);
1854  else if (buf.cmp("I") ||
1855  buf.cmp("EM"))
1856  pushfont(font |= FL_ITALIC, fsize);
1857  else if (buf.cmp("CODE") ||
1858  buf.cmp("TT"))
1859  pushfont(font = FL_COURIER, fsize);
1860  else if (buf.cmp("KBD"))
1861  pushfont(font = FL_COURIER_BOLD, fsize);
1862  else if (buf.cmp("VAR"))
1863  pushfont(font = FL_COURIER_ITALIC, fsize);
1864  else if (buf.cmp("/B") ||
1865  buf.cmp("/STRONG") ||
1866  buf.cmp("/I") ||
1867  buf.cmp("/EM") ||
1868  buf.cmp("/CODE") ||
1869  buf.cmp("/TT") ||
1870  buf.cmp("/KBD") ||
1871  buf.cmp("/VAR"))
1872  popfont(font, fsize, fcolor);
1873  else if (buf.cmp("IMG"))
1874  {
1875  Fl_Shared_Image *img = 0;
1876  int width;
1877  int height;
1878 
1879 
1880  get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
1881  get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
1882  width = get_length(wattr);
1883  height = get_length(hattr);
1884 
1885  if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
1886  img = get_image(attr, width, height);
1887  width = img->w();
1888  height = img->h();
1889  }
1890 
1891  ww = width;
1892 
1893  if (ww > hsize_) {
1894  hsize_ = ww;
1895  done = 0;
1896  break;
1897  }
1898 
1899  if (needspace && xx > block->x)
1900  ww += (int)fl_width(' ');
1901 
1902  if ((xx + ww) > block->w)
1903  {
1904  line = do_align(block, line, xx, newalign, links);
1905  xx = block->x;
1906  yy += hh;
1907  block->h += hh;
1908  hh = 0;
1909  }
1910 
1911  if (linkdest[0])
1912  add_link(linkdest, xx, yy-fsize, ww, height);
1913 
1914  xx += ww;
1915  if ((height + 2) > hh)
1916  hh = height + 2;
1917 
1918  needspace = 0;
1919  }
1920  buf.clear();
1921  }
1922  else if (*ptr == '\n' && pre)
1923  {
1924  if (linkdest[0])
1925  add_link(linkdest, xx, yy - hh, ww, hh);
1926 
1927  if (xx > hsize_) {
1928  hsize_ = xx;
1929  done = 0;
1930  break;
1931  }
1932 
1933  line = do_align(block, line, xx, newalign, links);
1934  xx = block->x;
1935  yy += hh;
1936  block->h += hh;
1937  needspace = 0;
1938  ptr ++;
1939  }
1940  else if (isspace((*ptr)&255))
1941  {
1942  needspace = 1;
1943  if ( pre ) {
1944  xx += (int)fl_width(' ');
1945  }
1946  ptr ++;
1947  }
1948  else if (*ptr == '&')
1949  {
1950  // Handle html '&' codes, eg. "&amp;"
1951  ptr ++;
1952 
1953  int qch = quote_char(ptr);
1954 
1955  if (qch < 0)
1956  buf.add('&');
1957  else {
1958  buf.add(qch);
1959  ptr = strchr(ptr, ';') + 1;
1960  }
1961 
1962  if ((fsize + 2) > hh)
1963  hh = fsize + 2;
1964  }
1965  else
1966  {
1967  buf.add(*ptr++);
1968 
1969  if ((fsize + 2) > hh)
1970  hh = fsize + 2;
1971  }
1972  }
1973 
1974  if (buf.size() > 0 && !head)
1975  {
1976  ww = buf.width();
1977 
1978  // printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n",
1979  // line, xx, ww, block->x, block->w);
1980 
1981  if (ww > hsize_) {
1982  hsize_ = ww;
1983  done = 0;
1984  break;
1985  }
1986 
1987  if (needspace && xx > block->x)
1988  ww += (int)fl_width(' ');
1989 
1990  if ((xx + ww) > block->w)
1991  {
1992  line = do_align(block, line, xx, newalign, links);
1993  xx = block->x;
1994  yy += hh;
1995  block->h += hh;
1996  hh = 0;
1997  }
1998 
1999  if (linkdest[0])
2000  add_link(linkdest, xx, yy - fsize, ww, fsize);
2001 
2002  xx += ww;
2003  }
2004 
2005  do_align(block, line, xx, newalign, links);
2006 
2007  block->end = ptr;
2008  size_ = yy + hh;
2009  }
2010 
2011 // printf("margins.depth_=%d\n", margins.depth_);
2012 
2013  if (ntargets_ > 1)
2014  qsort(targets_, ntargets_, sizeof(Fl_Help_Target),
2016 
2017  int dx = Fl::box_dw(b) - Fl::box_dx(b);
2018  int dy = Fl::box_dh(b) - Fl::box_dy(b);
2020  int dw = Fl::box_dw(b) + ss;
2021  int dh = Fl::box_dh(b);
2022 
2023  if (hsize_ > (w() - dw)) {
2024  hscrollbar_.show();
2025 
2026  dh += ss;
2027 
2028  if (size_ < (h() - dh)) {
2029  scrollbar_.hide();
2030  hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - ss - dy,
2031  w() - Fl::box_dw(b), ss);
2032  } else {
2033  scrollbar_.show();
2034  scrollbar_.resize(x() + w() - ss - dx, y() + Fl::box_dy(b),
2035  ss, h() - ss - Fl::box_dh(b));
2036  hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - ss - dy,
2037  w() - ss - Fl::box_dw(b), ss);
2038  }
2039  } else {
2040  hscrollbar_.hide();
2041 
2042  if (size_ < (h() - dh)) scrollbar_.hide();
2043  else {
2044  scrollbar_.resize(x() + w() - ss - dx, y() + Fl::box_dy(b),
2045  ss, h() - Fl::box_dh(b));
2046  scrollbar_.show();
2047  }
2048  }
2049 
2050  // Reset scrolling if it needs to be...
2051  if (scrollbar_.visible()) {
2052  int temph = h() - Fl::box_dh(b);
2053  if (hscrollbar_.visible()) temph -= ss;
2054  if ((topline_ + temph) > size_) topline(size_ - temph);
2055  else topline(topline_);
2056  } else topline(0);
2057 
2058  if (hscrollbar_.visible()) {
2059  int tempw = w() - ss - Fl::box_dw(b);
2060  if ((leftline_ + tempw) > hsize_) leftline(hsize_ - tempw);
2061  else leftline(leftline_);
2062  } else leftline(0);
2063 }
2064 
2065 
2067 void
2068 Fl_Help_View::format_table(int *table_width, // O - Total table width
2069  int *columns, // O - Column widths
2070  const char *table) // I - Pointer to start of table
2071 {
2072  int column, // Current column
2073  num_columns, // Number of columns
2074  colspan, // COLSPAN attribute
2075  width, // Current width
2076  temp_width, // Temporary width
2077  max_width, // Maximum width
2078  incell, // In a table cell?
2079  pre, // <PRE> text?
2080  needspace; // Need whitespace?
2081  HV_Edit_Buffer buf; // Text buffer
2082  char attr[1024], // Other attribute
2083  wattr[1024], // WIDTH attribute
2084  hattr[1024]; // HEIGHT attribute
2085  const char *ptr, // Pointer into table
2086  *attrs, // Pointer to attributes
2087  *start; // Start of element
2088  int minwidths[MAX_COLUMNS]; // Minimum widths for each column
2089  Fl_Font font;
2090  Fl_Fontsize fsize; // Current font and size
2091  Fl_Color fcolor; // Currrent font color
2092 
2093  DEBUG_FUNCTION(__LINE__,__FUNCTION__);
2094 
2095  // Clear widths...
2096  *table_width = 0;
2097  for (column = 0; column < MAX_COLUMNS; column ++)
2098  {
2099  columns[column] = 0;
2100  minwidths[column] = 0;
2101  }
2102 
2103  num_columns = 0;
2104  colspan = 0;
2105  max_width = 0;
2106  pre = 0;
2107  needspace = 0;
2108  fstack_.top(font, fsize, fcolor);
2109 
2110  // Scan the table...
2111  for (ptr = table, column = -1, width = 0, incell = 0; *ptr;)
2112  {
2113  if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0 && incell)
2114  {
2115  // Check width...
2116  if (needspace)
2117  {
2118  buf.add(' ');
2119  needspace = 0;
2120  }
2121 
2122  temp_width = buf.width();
2123  buf.clear();
2124 
2125  if (temp_width > minwidths[column])
2126  minwidths[column] = temp_width;
2127 
2128  width += temp_width;
2129 
2130  if (width > max_width)
2131  max_width = width;
2132  }
2133 
2134  if (*ptr == '<')
2135  {
2136  start = ptr;
2137 
2138  for (buf.clear(), ptr ++; *ptr && *ptr != '>' && !isspace((*ptr)&255);)
2139  buf.add(*ptr++);
2140 
2141  attrs = ptr;
2142  while (*ptr && *ptr != '>')
2143  ptr ++;
2144 
2145  if (*ptr == '>')
2146  ptr ++;
2147 
2148  if (buf.cmp("BR") ||
2149  buf.cmp("HR"))
2150  {
2151  width = 0;
2152  needspace = 0;
2153  }
2154  else if (buf.cmp("TABLE") && start > table)
2155  break;
2156  else if (buf.cmp("CENTER") ||
2157  buf.cmp("P") ||
2158  buf.cmp("H1") ||
2159  buf.cmp("H2") ||
2160  buf.cmp("H3") ||
2161  buf.cmp("H4") ||
2162  buf.cmp("H5") ||
2163  buf.cmp("H6") ||
2164  buf.cmp("UL") ||
2165  buf.cmp("OL") ||
2166  buf.cmp("DL") ||
2167  buf.cmp("LI") ||
2168  buf.cmp("DD") ||
2169  buf.cmp("DT") ||
2170  buf.cmp("PRE"))
2171  {
2172  width = 0;
2173  needspace = 0;
2174 
2175  if (tolower(buf[0]) == 'h' && isdigit(buf[1]))
2176  {
2177  font = FL_HELVETICA_BOLD;
2178  fsize = textsize_ + '7' - buf[1];
2179  }
2180  else if (buf.cmp("DT"))
2181  {
2182  font = textfont_ | FL_ITALIC;
2183  fsize = textsize_;
2184  }
2185  else if (buf.cmp("PRE"))
2186  {
2187  font = FL_COURIER;
2188  fsize = textsize_;
2189  pre = 1;
2190  }
2191  else if (buf.cmp("LI"))
2192  {
2193  width += 4 * fsize;
2194  font = textfont_;
2195  fsize = textsize_;
2196  }
2197  else
2198  {
2199  font = textfont_;
2200  fsize = textsize_;
2201  }
2202 
2203  pushfont(font, fsize);
2204  }
2205  else if (buf.cmp("/CENTER") ||
2206  buf.cmp("/P") ||
2207  buf.cmp("/H1") ||
2208  buf.cmp("/H2") ||
2209  buf.cmp("/H3") ||
2210  buf.cmp("/H4") ||
2211  buf.cmp("/H5") ||
2212  buf.cmp("/H6") ||
2213  buf.cmp("/PRE") ||
2214  buf.cmp("/UL") ||
2215  buf.cmp("/OL") ||
2216  buf.cmp("/DL"))
2217  {
2218  width = 0;
2219  needspace = 0;
2220 
2221  popfont(font, fsize, fcolor);
2222  }
2223  else if (buf.cmp("TR") || buf.cmp("/TR") ||
2224  buf.cmp("/TABLE"))
2225  {
2226 // printf("%s column = %d, colspan = %d, num_columns = %d\n",
2227 // buf.c_str(), column, colspan, num_columns);
2228 
2229  if (column >= 0)
2230  {
2231  // This is a hack to support COLSPAN...
2232  max_width /= colspan;
2233 
2234  while (colspan > 0)
2235  {
2236  if (max_width > columns[column])
2237  columns[column] = max_width;
2238 
2239  column ++;
2240  colspan --;
2241  }
2242  }
2243 
2244  if (buf.cmp("/TABLE"))
2245  break;
2246 
2247  needspace = 0;
2248  column = -1;
2249  width = 0;
2250  max_width = 0;
2251  incell = 0;
2252  }
2253  else if (buf.cmp("TD") ||
2254  buf.cmp("TH"))
2255  {
2256 // printf("BEFORE column = %d, colspan = %d, num_columns = %d\n",
2257 // column, colspan, num_columns);
2258 
2259  if (column >= 0)
2260  {
2261  // This is a hack to support COLSPAN...
2262  max_width /= colspan;
2263 
2264  while (colspan > 0)
2265  {
2266  if (max_width > columns[column])
2267  columns[column] = max_width;
2268 
2269  column ++;
2270  colspan --;
2271  }
2272  }
2273  else
2274  column ++;
2275 
2276  if (get_attr(attrs, "COLSPAN", attr, sizeof(attr)) != NULL)
2277  colspan = atoi(attr);
2278  else
2279  colspan = 1;
2280 
2281 // printf("AFTER column = %d, colspan = %d, num_columns = %d\n",
2282 // column, colspan, num_columns);
2283 
2284  if ((column + colspan) >= num_columns)
2285  num_columns = column + colspan;
2286 
2287  needspace = 0;
2288  width = 0;
2289  incell = 1;
2290 
2291  if (buf.cmp("TH"))
2292  font = textfont_ | FL_BOLD;
2293  else
2294  font = textfont_;
2295 
2296  fsize = textsize_;
2297 
2298  pushfont(font, fsize);
2299 
2300  if (get_attr(attrs, "WIDTH", attr, sizeof(attr)) != NULL)
2301  max_width = get_length(attr);
2302  else
2303  max_width = 0;
2304 
2305 // printf("max_width = %d\n", max_width);
2306  }
2307  else if (buf.cmp("/TD") ||
2308  buf.cmp("/TH"))
2309  {
2310  incell = 0;
2311  popfont(font, fsize, fcolor);
2312  }
2313  else if (buf.cmp("B") ||
2314  buf.cmp("STRONG"))
2315  pushfont(font |= FL_BOLD, fsize);
2316  else if (buf.cmp("I") ||
2317  buf.cmp("EM"))
2318  pushfont(font |= FL_ITALIC, fsize);
2319  else if (buf.cmp("CODE") ||
2320  buf.cmp("TT"))
2321  pushfont(font = FL_COURIER, fsize);
2322  else if (buf.cmp("KBD"))
2323  pushfont(font = FL_COURIER_BOLD, fsize);
2324  else if (buf.cmp("VAR"))
2325  pushfont(font = FL_COURIER_ITALIC, fsize);
2326  else if (buf.cmp("/B") ||
2327  buf.cmp("/STRONG") ||
2328  buf.cmp("/I") ||
2329  buf.cmp("/EM") ||
2330  buf.cmp("/CODE") ||
2331  buf.cmp("/TT") ||
2332  buf.cmp("/KBD") ||
2333  buf.cmp("/VAR"))
2334  popfont(font, fsize, fcolor);
2335  else if (buf.cmp("IMG") && incell)
2336  {
2337  Fl_Shared_Image *img = 0;
2338  int iwidth, iheight;
2339 
2340 
2341  get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
2342  get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
2343  iwidth = get_length(wattr);
2344  iheight = get_length(hattr);
2345 
2346  if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
2347  img = get_image(attr, iwidth, iheight);
2348  iwidth = img->w();
2349  iheight = img->h();
2350  }
2351 
2352  if (iwidth > minwidths[column])
2353  minwidths[column] = iwidth;
2354 
2355  width += iwidth;
2356  if (needspace)
2357  width += (int)fl_width(' ');
2358 
2359  if (width > max_width)
2360  max_width = width;
2361 
2362  needspace = 0;
2363  }
2364  buf.clear();
2365  }
2366  else if (*ptr == '\n' && pre)
2367  {
2368  width = 0;
2369  needspace = 0;
2370  ptr ++;
2371  }
2372  else if (isspace((*ptr)&255))
2373  {
2374  needspace = 1;
2375 
2376  ptr ++;
2377  }
2378  else if (*ptr == '&' )
2379  {
2380  ptr ++;
2381 
2382  int qch = quote_char(ptr);
2383 
2384  if (qch < 0)
2385  buf.add('&');
2386  else {
2387  buf.add(qch);
2388  ptr = strchr(ptr, ';') + 1;
2389  }
2390  }
2391  else
2392  {
2393  buf.add(*ptr++);
2394  }
2395  }
2396 
2397  // Now that we have scanned the entire table, adjust the table and
2398  // cell widths to fit on the screen...
2399  if (get_attr(table + 6, "WIDTH", attr, sizeof(attr)))
2400  *table_width = get_length(attr);
2401  else
2402  *table_width = 0;
2403 
2404 #ifdef DEBUG
2405  printf("num_columns = %d, table_width = %d\n", num_columns, *table_width);
2406 #endif // DEBUG
2407 
2408  if (num_columns == 0)
2409  return;
2410 
2411  // Add up the widths...
2412  for (column = 0, width = 0; column < num_columns; column ++)
2413  width += columns[column];
2414 
2415 #ifdef DEBUG
2416  printf("width = %d, w() = %d\n", width, w());
2417  for (column = 0; column < num_columns; column ++)
2418  printf(" columns[%d] = %d, minwidths[%d] = %d\n", column, columns[column],
2419  column, minwidths[column]);
2420 #endif // DEBUG
2421 
2422  // Adjust the width if needed...
2423  int scale_width = *table_width;
2424 
2425  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
2426  if (scale_width == 0) {
2427  if (width > (hsize_ - scrollsize)) scale_width = hsize_ - scrollsize;
2428  else scale_width = width;
2429  }
2430 
2431  if (width < scale_width) {
2432 #ifdef DEBUG
2433  printf("Scaling table up to %d from %d...\n", scale_width, width);
2434 #endif // DEBUG
2435 
2436  *table_width = 0;
2437 
2438  scale_width = (scale_width - width) / num_columns;
2439 
2440 #ifdef DEBUG
2441  printf("adjusted scale_width = %d\n", scale_width);
2442 #endif // DEBUG
2443 
2444  for (column = 0; column < num_columns; column ++) {
2445  columns[column] += scale_width;
2446 
2447  (*table_width) += columns[column];
2448  }
2449  }
2450  else if (width > scale_width) {
2451 #ifdef DEBUG
2452  printf("Scaling table down to %d from %d...\n", scale_width, width);
2453 #endif // DEBUG
2454 
2455  for (column = 0; column < num_columns; column ++) {
2456  width -= minwidths[column];
2457  scale_width -= minwidths[column];
2458  }
2459 
2460 #ifdef DEBUG
2461  printf("adjusted width = %d, scale_width = %d\n", width, scale_width);
2462 #endif // DEBUG
2463 
2464  if (width > 0) {
2465  for (column = 0; column < num_columns; column ++) {
2466  columns[column] -= minwidths[column];
2467  columns[column] = scale_width * columns[column] / width;
2468  columns[column] += minwidths[column];
2469  }
2470  }
2471 
2472  *table_width = 0;
2473  for (column = 0; column < num_columns; column ++) {
2474  (*table_width) += columns[column];
2475  }
2476  }
2477  else if (*table_width == 0)
2478  *table_width = width;
2479 
2480 #ifdef DEBUG
2481  printf("FINAL table_width = %d\n", *table_width);
2482  for (column = 0; column < num_columns; column ++)
2483  printf(" columns[%d] = %d\n", column, columns[column]);
2484 #endif // DEBUG
2485 }
2486 
2487 
2489 void
2491  // Release all images...
2492  if (value_) {
2493  const char *ptr, // Pointer into block
2494  *attrs; // Pointer to start of element attributes
2495  HV_Edit_Buffer buf; // Text buffer
2496  char attr[1024], // Attribute buffer
2497  wattr[1024], // Width attribute buffer
2498  hattr[1024]; // Height attribute buffer
2499 
2500  DEBUG_FUNCTION(__LINE__,__FUNCTION__);
2501 
2502  for (ptr = value_; *ptr;)
2503  {
2504  if (*ptr == '<')
2505  {
2506  ptr ++;
2507 
2508  if (strncmp(ptr, "!--", 3) == 0)
2509  {
2510  // Comment...
2511  ptr += 3;
2512  if ((ptr = strstr(ptr, "-->")) != NULL)
2513  {
2514  ptr += 3;
2515  continue;
2516  }
2517  else
2518  break;
2519  }
2520 
2521  buf.clear();
2522 
2523  while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
2524  buf.add(*ptr++);
2525 
2526  attrs = ptr;
2527  while (*ptr && *ptr != '>')
2528  ptr ++;
2529 
2530  if (*ptr == '>')
2531  ptr ++;
2532 
2533  if (buf.cmp("IMG"))
2534  {
2535  Fl_Shared_Image *img;
2536  int width;
2537  int height;
2538 
2539  get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
2540  get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
2541  width = get_length(wattr);
2542  height = get_length(hattr);
2543 
2544  if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
2545  // Get and release the image to free it from memory...
2546  img = get_image(attr, width, height);
2547  if ((void*)img != &broken_image) {
2548  img->release();
2549  }
2550  }
2551  }
2552  }
2553  else
2554  ptr ++;
2555  }
2556 
2557  free((void *)value_);
2558  value_ = 0;
2559  }
2560 
2561  // Free all of the arrays...
2562  if (nblocks_) {
2563  free(blocks_);
2564 
2565  ablocks_ = 0;
2566  nblocks_ = 0;
2567  blocks_ = 0;
2568  }
2569 
2570  if (nlinks_) {
2571  free(links_);
2572 
2573  alinks_ = 0;
2574  nlinks_ = 0;
2575  links_ = 0;
2576  }
2577 
2578  if (ntargets_) {
2579  free(targets_);
2580 
2581  atargets_ = 0;
2582  ntargets_ = 0;
2583  targets_ = 0;
2584  }
2585 } // free_data()
2586 
2588 int // O - Alignment
2589 Fl_Help_View::get_align(const char *p, // I - Pointer to start of attrs
2590  int a) // I - Default alignment
2591 {
2592  char buf[255]; // Alignment value
2593 
2594 
2595  if (get_attr(p, "ALIGN", buf, sizeof(buf)) == NULL)
2596  return (a);
2597 
2598  if (strcasecmp(buf, "CENTER") == 0)
2599  return (CENTER);
2600  else if (strcasecmp(buf, "RIGHT") == 0)
2601  return (RIGHT);
2602  else
2603  return (LEFT);
2604 }
2605 
2606 
2608 const char * // O - Pointer to buf or NULL
2609 Fl_Help_View::get_attr(const char *p, // I - Pointer to start of attributes
2610  const char *n, // I - Name of attribute
2611  char *buf, // O - Buffer for attribute value
2612  int bufsize) // I - Size of buffer
2613 {
2614  char name[255], // Name from string
2615  *ptr, // Pointer into name or value
2616  quote; // Quote
2617 
2618 
2619  buf[0] = '\0';
2620 
2621  while (*p && *p != '>')
2622  {
2623  while (isspace((*p)&255))
2624  p ++;
2625 
2626  if (*p == '>' || !*p)
2627  return (NULL);
2628 
2629  for (ptr = name; *p && !isspace((*p)&255) && *p != '=' && *p != '>';)
2630  if (ptr < (name + sizeof(name) - 1))
2631  *ptr++ = *p++;
2632  else
2633  p ++;
2634 
2635  *ptr = '\0';
2636 
2637  if (isspace((*p)&255) || !*p || *p == '>')
2638  buf[0] = '\0';
2639  else
2640  {
2641  if (*p == '=')
2642  p ++;
2643 
2644  for (ptr = buf; *p && !isspace((*p)&255) && *p != '>';)
2645  if (*p == '\'' || *p == '\"')
2646  {
2647  quote = *p++;
2648 
2649  while (*p && *p != quote)
2650  if ((ptr - buf + 1) < bufsize)
2651  *ptr++ = *p++;
2652  else
2653  p ++;
2654 
2655  if (*p == quote)
2656  p ++;
2657  }
2658  else if ((ptr - buf + 1) < bufsize)
2659  *ptr++ = *p++;
2660  else
2661  p ++;
2662 
2663  *ptr = '\0';
2664  }
2665 
2666  if (strcasecmp(n, name) == 0)
2667  return (buf);
2668  else
2669  buf[0] = '\0';
2670 
2671  if (*p == '>')
2672  return (NULL);
2673  }
2674 
2675  return (NULL);
2676 }
2677 
2678 
2680 Fl_Color // O - Color value
2681 Fl_Help_View::get_color(const char *n, // I - Color name
2682  Fl_Color c) // I - Default color value
2683 {
2684  int i; // Looping var
2685  int rgb, r, g, b; // RGB values
2686  static const struct { // Color name table
2687  const char *name;
2688  int r, g, b;
2689  } colors[] = {
2690  { "black", 0x00, 0x00, 0x00 },
2691  { "red", 0xff, 0x00, 0x00 },
2692  { "green", 0x00, 0x80, 0x00 },
2693  { "yellow", 0xff, 0xff, 0x00 },
2694  { "blue", 0x00, 0x00, 0xff },
2695  { "magenta", 0xff, 0x00, 0xff },
2696  { "fuchsia", 0xff, 0x00, 0xff },
2697  { "cyan", 0x00, 0xff, 0xff },
2698  { "aqua", 0x00, 0xff, 0xff },
2699  { "white", 0xff, 0xff, 0xff },
2700  { "gray", 0x80, 0x80, 0x80 },
2701  { "grey", 0x80, 0x80, 0x80 },
2702  { "lime", 0x00, 0xff, 0x00 },
2703  { "maroon", 0x80, 0x00, 0x00 },
2704  { "navy", 0x00, 0x00, 0x80 },
2705  { "olive", 0x80, 0x80, 0x00 },
2706  { "purple", 0x80, 0x00, 0x80 },
2707  { "silver", 0xc0, 0xc0, 0xc0 },
2708  { "teal", 0x00, 0x80, 0x80 }
2709  };
2710 
2711 
2712  if (!n || !n[0]) return c;
2713 
2714  if (n[0] == '#') {
2715  // Do hex color lookup
2716  rgb = strtol(n + 1, NULL, 16);
2717 
2718  if (strlen(n) > 4) {
2719  r = rgb >> 16;
2720  g = (rgb >> 8) & 255;
2721  b = rgb & 255;
2722  } else {
2723  r = (rgb >> 8) * 17;
2724  g = ((rgb >> 4) & 15) * 17;
2725  b = (rgb & 15) * 17;
2726  }
2727  return (fl_rgb_color((uchar)r, (uchar)g, (uchar)b));
2728  } else {
2729  for (i = 0; i < (int)(sizeof(colors) / sizeof(colors[0])); i ++)
2730  if (!strcasecmp(n, colors[i].name)) {
2731  return fl_rgb_color(colors[i].r, colors[i].g, colors[i].b);
2732  }
2733  return c;
2734  }
2735 }
2736 
2737 
2751 /* Implementation note: (A.S. Apr 05, 2009)
2752 
2753  Fl_Help_View::get_image() uses a static global flag (initial_load)
2754  to determine, if it is called from the initial loading of a document
2755  (load() or value()), or from resize() or draw().
2756 
2757  A better solution would be to manage all loaded images in an own
2758  structure like Fl_Help_Target (Fl_Help_Image ?) to avoid using this
2759  global flag, but this would break the ABI !
2760 
2761  This should be fixed in FLTK 1.3 !
2762 
2763 
2764  If initial_load is true, then Fl_Shared_Image::get() is called to
2765  load the image, and the reference count of the shared image is
2766  increased by one.
2767 
2768  If initial_load is false, then Fl_Shared_Image::find() is called to
2769  load the image, and the image is released immediately. This avoids
2770  increasing the reference count when calling get_image() from draw()
2771  or resize().
2772 
2773  Calling Fl_Shared_Image::find() instead of Fl_Shared_Image::get() avoids
2774  doing unnecessary i/o for "broken images" within each resize/redraw.
2775 
2776  Each image must be released exactly once in the destructor or before
2777  a new document is loaded: see free_data().
2778 */
2779 
2781 Fl_Help_View::get_image(const char *name, int W, int H) {
2782  const char *localname; // Local filename
2783  char dir[FL_PATH_MAX]; // Current directory
2784  char temp[FL_PATH_MAX], // Temporary filename
2785  *tempptr; // Pointer into temporary name
2786  Fl_Shared_Image *ip; // Image pointer...
2787 
2788  // See if the image can be found...
2789  if (strchr(directory_, ':') != NULL && strchr(name, ':') == NULL) {
2790  if (name[0] == '/') {
2791  strlcpy(temp, directory_, sizeof(temp));
2792 
2793  if ((tempptr = strrchr(strchr(directory_, ':') + 3, '/')) != NULL) {
2794  strlcpy(tempptr, name, sizeof(temp) - (tempptr - temp));
2795  } else {
2796  strlcat(temp, name, sizeof(temp));
2797  }
2798  } else {
2799  snprintf(temp, sizeof(temp), "%s/%s", directory_, name);
2800  }
2801 
2802  if (link_) localname = (*link_)(this, temp);
2803  else localname = temp;
2804  } else if (name[0] != '/' && strchr(name, ':') == NULL) {
2805  if (directory_[0]) snprintf(temp, sizeof(temp), "%s/%s", directory_, name);
2806  else {
2807  fl_getcwd(dir, sizeof(dir));
2808  snprintf(temp, sizeof(temp), "file:%s/%s", dir, name);
2809  }
2810 
2811  if (link_) localname = (*link_)(this, temp);
2812  else localname = temp;
2813  } else if (link_) localname = (*link_)(this, name);
2814  else localname = name;
2815 
2816  if (!localname) return 0;
2817 
2818  if (strncmp(localname, "file:", 5) == 0) localname += 5;
2819 
2820  if (initial_load) {
2821  if ((ip = Fl_Shared_Image::get(localname, W, H)) == NULL) {
2822  ip = (Fl_Shared_Image *)&broken_image;
2823  }
2824  } else { // draw or resize
2825  if ((ip = Fl_Shared_Image::find(localname, W, H)) == NULL) {
2826  ip = (Fl_Shared_Image *)&broken_image;
2827  } else {
2828  ip->release();
2829  }
2830  }
2831 
2832  return ip;
2833 }
2834 
2835 
2837 int
2838 Fl_Help_View::get_length(const char *l) { // I - Value
2839  int val; // Integer value
2840 
2841  if (!l[0]) return 0;
2842 
2843  val = atoi(l);
2844  if (l[strlen(l) - 1] == '%') {
2845  if (val > 100) val = 100;
2846  else if (val < 0) val = 0;
2847 
2848  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
2849  val = val * (hsize_ - scrollsize) / 100;
2850  }
2851 
2852  return val;
2853 }
2854 
2855 
2857 {
2858  int i;
2859  Fl_Help_Link *linkp;
2860  for (i = nlinks_, linkp = links_; i > 0; i --, linkp ++) {
2861  if (xx >= linkp->x && xx < linkp->w &&
2862  yy >= linkp->y && yy < linkp->h)
2863  break;
2864  }
2865  return i ? linkp : 0L;
2866 }
2867 
2869 {
2870  char target[32]; // Current target
2871 
2872  clear_selection();
2873 
2874  strlcpy(target, linkp->name, sizeof(target));
2875 
2876  set_changed();
2877 
2878  if (strcmp(linkp->filename, filename_) != 0 && linkp->filename[0])
2879  {
2880  char dir[FL_PATH_MAX]; // Current directory
2881  char temp[FL_PATH_MAX], // Temporary filename
2882  *tempptr; // Pointer into temporary filename
2883 
2884 
2885  if (strchr(directory_, ':') != NULL &&
2886  strchr(linkp->filename, ':') == NULL)
2887  {
2888  if (linkp->filename[0] == '/')
2889  {
2890  strlcpy(temp, directory_, sizeof(temp));
2891  if ((tempptr = strrchr(strchr(directory_, ':') + 3, '/')) != NULL)
2892  strlcpy(tempptr, linkp->filename, sizeof(temp));
2893  else
2894  strlcat(temp, linkp->filename, sizeof(temp));
2895  }
2896  else
2897  snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename);
2898  }
2899  else if (linkp->filename[0] != '/' && strchr(linkp->filename, ':') == NULL)
2900  {
2901  if (directory_[0])
2902  snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename);
2903  else
2904  {
2905  fl_getcwd(dir, sizeof(dir));
2906  snprintf(temp, sizeof(temp), "file:%s/%s", dir, linkp->filename);
2907  }
2908  }
2909  else
2910  strlcpy(temp, linkp->filename, sizeof(temp));
2911 
2912  if (linkp->name[0])
2913  snprintf(temp + strlen(temp), sizeof(temp) - strlen(temp), "#%s",
2914  linkp->name);
2915 
2916  load(temp);
2917  }
2918  else if (target[0])
2919  topline(target);
2920  else
2921  topline(0);
2922 
2923  leftline(0);
2924 }
2925 
2928 {
2929  if (current_view==this)
2931 }
2934 {
2936  if (!value_) return;
2937  current_view = this;
2938  selection_drag_last = selection_last = (int) strlen(value_);
2939  selected = 1;
2940 }
2941 
2943 {
2944  if (selected) redraw();
2948  selected = 0;
2949 }
2950 
2952 {
2954 
2956 
2957  mouse_x = Fl::event_x();
2958  mouse_y = Fl::event_y();
2959  draw_mode = 1;
2960 
2961  current_view = this;
2963  draw();
2964  fl_end_offscreen();
2965 
2966  draw_mode = 0;
2967 
2968  if (selection_push_last) return 1;
2969  else return 0;
2970 }
2971 
2973 {
2974  if (Fl::event_is_click())
2975  return 0;
2976 
2977 // printf("old selection_first=%d, selection_last=%d\n",
2978 // selection_first, selection_last);
2979 
2980  int sf = selection_first, sl = selection_last;
2981 
2982  selected = 1;
2983  mouse_x = Fl::event_x();
2984  mouse_y = Fl::event_y();
2985  draw_mode = 2;
2986 
2988  draw();
2989  fl_end_offscreen();
2990 
2991  draw_mode = 0;
2992 
2995  } else {
2997  }
2998 
3001  } else {
3003  }
3004 
3005 // printf("new selection_first=%d, selection_last=%d\n",
3006 // selection_first, selection_last);
3007 
3008  if (sf!=selection_first || sl!=selection_last) {
3009 // puts("REDRAW!!!\n");
3010  return 1;
3011  } else {
3012 // puts("");
3013  return 0;
3014  }
3015 }
3016 
3017 // convert a command with up to four letters into an unsigned int
3018 static unsigned int command(const char *cmd)
3019 {
3020  unsigned int ret = (tolower(cmd[0])<<24);
3021  char c = cmd[1];
3022  if (c=='>' || c==' ' || c==0) return ret;
3023  ret |= (tolower(c)<<16);
3024  c = cmd[2];
3025  if (c=='>' || c==' ' || c==0) return ret;
3026  ret |= (tolower(c)<<8);
3027  c = cmd[3];
3028  if (c=='>' || c==' ' || c==0) return ret;
3029  ret |= tolower(c);
3030  c = cmd[4];
3031  if (c=='>' || c==' ' || c==0) return ret;
3032  return 0;
3033 }
3034 
3035 #define CMD(a, b, c, d) ((a<<24)|(b<<16)|(c<<8)|d)
3036 
3037 void Fl_Help_View::end_selection(int clipboard)
3038 {
3039  if (!selected || current_view!=this)
3040  return;
3041  // convert the select part of our html text into some kind of somewhat readable UTF-8
3042  // and store it in the selection buffer
3043  int p = 0;
3044  char pre = 0;
3045  int len = (int) strlen(value_);
3046  char *txt = (char*)malloc(len+1), *d = txt;
3047  const char *s = value_, *cmd, *src;
3048  for (;;) {
3049  int c = (*s++) & 0xff;
3050  if (c==0) break;
3051  if (c=='<') { // begin of some html command. Skip until we find a '>'
3052  cmd = s;
3053  for (;;) {
3054  c = (*s++) & 0xff;
3055  if (c==0 || c=='>') break;
3056  }
3057  if (c==0) break;
3058  // do something with this command... .
3059  // The replacement string must not be longer than the command
3060  // itself plus '<' and '>'
3061  src = 0;
3062  switch (command(cmd)) {
3063  case CMD('p','r','e', 0 ): pre = 1; break;
3064  case CMD('/','p','r','e'): pre = 0; break;
3065  case CMD('t','d', 0 , 0 ):
3066  case CMD('p', 0 , 0 , 0 ):
3067  case CMD('/','p', 0 , 0 ):
3068  case CMD('b','r', 0 , 0 ): src = "\n"; break;
3069  case CMD('l','i', 0 , 0 ): src = "\n * "; break;
3070  case CMD('/','h','1', 0 ):
3071  case CMD('/','h','2', 0 ):
3072  case CMD('/','h','3', 0 ):
3073  case CMD('/','h','4', 0 ):
3074  case CMD('/','h','5', 0 ):
3075  case CMD('/','h','6', 0 ): src = "\n\n"; break;
3076  case CMD('t','r', 0 , 0 ):
3077  case CMD('h','1', 0 , 0 ):
3078  case CMD('h','2', 0 , 0 ):
3079  case CMD('h','3', 0 , 0 ):
3080  case CMD('h','4', 0 , 0 ):
3081  case CMD('h','5', 0 , 0 ):
3082  case CMD('h','6', 0 , 0 ): src = "\n\n"; break;
3083  case CMD('d','t', 0 , 0 ): src = "\n "; break;
3084  case CMD('d','d', 0 , 0 ): src = "\n - "; break;
3085  }
3086  int n = (int) (s-value_);
3087  if (src && n>selection_first && n<=selection_last) {
3088  while (*src) {
3089  *d++ = *src++;
3090  }
3091  c = src[-1] & 0xff;
3092  p = isspace(c) ? ' ' : c;
3093  }
3094  continue;
3095  }
3096  const char *s2 = s;
3097  if (c=='&') { // special characters (HTML entities)
3098  int xx = quote_char(s);
3099  if (xx >= 0) {
3100  c = xx;
3101  for (;;) {
3102  char cc = *s++;
3103  if (!cc || cc==';') break;
3104  }
3105  }
3106  }
3107  int n = (int) (s2-value_);
3108  if (n>selection_first && n<=selection_last) {
3109  if (!pre && c < 256 && isspace(c)) c = ' ';
3110  if (p != ' ' || c != ' ') {
3111  if (s2 != s) { // c was an HTML entity
3112  d += fl_utf8encode(c, d);
3113  }
3114  else *d++ = c;
3115  }
3116  p = c;
3117  }
3118  if (n>selection_last) break; // stop parsing html after end of selection
3119  }
3120  *d = 0;
3121  Fl::copy(txt, (int) strlen(txt), clipboard);
3122  // printf("copy [%s]\n", txt);
3123  free(txt);
3124 }
3125 
3127 int // O - 1 if we handled it, 0 otherwise
3128 Fl_Help_View::handle(int event) // I - Event to handle
3129 {
3130  static Fl_Help_Link *linkp; // currently clicked link
3131 
3132  int xx = Fl::event_x() - x() + leftline_;
3133  int yy = Fl::event_y() - y() + topline_;
3134 
3135  switch (event)
3136  {
3137  case FL_FOCUS:
3138  redraw();
3139  return 1;
3140  case FL_UNFOCUS:
3141  clear_selection();
3142  redraw();
3143  return 1;
3144  case FL_ENTER :
3145  Fl_Group::handle(event);
3146  return 1;
3147  case FL_LEAVE :
3149  break;
3150  case FL_MOVE:
3151  if (find_link(xx, yy)) fl_cursor(FL_CURSOR_HAND);
3153  return 1;
3154  case FL_PUSH:
3155  if (Fl_Group::handle(event)) return 1;
3156  linkp = find_link(xx, yy);
3157  if (linkp) {
3159  return 1;
3160  }
3161  if (begin_selection()) {
3163  return 1;
3164  }
3166  return 1;
3167  case FL_DRAG:
3168  if (linkp) {
3169  if (Fl::event_is_click()) {
3171  } else {
3172  fl_cursor(FL_CURSOR_DEFAULT); // should be "FL_CURSOR_CANCEL" if we had it
3173  }
3174  return 1;
3175  }
3176  if (current_view==this && selection_push_last) {
3177  if (extend_selection()) redraw();
3179  return 1;
3180  }
3182  return 1;
3183  case FL_RELEASE:
3184  if (linkp) {
3185  if (Fl::event_is_click()) {
3186  follow_link(linkp);
3187  }
3189  linkp = 0;
3190  return 1;
3191  }
3192  if (current_view==this && selection_push_last) {
3193  end_selection();
3194  return 1;
3195  }
3196  return 1;
3197  case FL_SHORTCUT: {
3198  int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT|FL_SHIFT);
3199  if ( mods == FL_COMMAND) {
3200  switch ( Fl::event_key() ) {
3201  case 'a': select_all(); redraw(); return 1;
3202  case 'c':
3203  case 'x': end_selection(1); return 1;
3204  }
3205  }
3206  break; }
3207  }
3208  return (Fl_Group::handle(event));
3209 }
3210 
3215 Fl_Help_View::Fl_Help_View(int xx, // I - Left position
3216  int yy, // I - Top position
3217  int ww, // I - Width in pixels
3218  int hh, // I - Height in pixels
3219  const char *l)
3220  : Fl_Group(xx, yy, ww, hh, l),
3221  scrollbar_(xx + ww - Fl::scrollbar_size(), yy,
3222  Fl::scrollbar_size(), hh - Fl::scrollbar_size()),
3223  hscrollbar_(xx, yy + hh - Fl::scrollbar_size(),
3224  ww - Fl::scrollbar_size(), Fl::scrollbar_size())
3225 {
3227 
3228  title_[0] = '\0';
3233  textfont_ = FL_TIMES;
3234  textsize_ = 12;
3235  value_ = NULL;
3236 
3237  ablocks_ = 0;
3238  nblocks_ = 0;
3239  blocks_ = (Fl_Help_Block *)0;
3240 
3241  link_ = (Fl_Help_Func *)0;
3242 
3243  alinks_ = 0;
3244  nlinks_ = 0;
3245  links_ = (Fl_Help_Link *)0;
3246 
3247  atargets_ = 0;
3248  ntargets_ = 0;
3249  targets_ = (Fl_Help_Target *)0;
3250 
3251  directory_[0] = '\0';
3252  filename_[0] = '\0';
3253 
3254  topline_ = 0;
3255  leftline_ = 0;
3256  size_ = 0;
3257  hsize_ = 0;
3258  scrollbar_size_ = 0;
3259 
3260  scrollbar_.value(0, hh, 0, 1);
3261  scrollbar_.step(8.0);
3262  scrollbar_.show();
3264 
3265  hscrollbar_.value(0, ww, 0, 1);
3266  hscrollbar_.step(8.0);
3267  hscrollbar_.show();
3270  end();
3271 
3272  resize(xx, yy, ww, hh);
3273 }
3274 
3275 
3282 {
3283  clear_selection();
3284  free_data();
3285 }
3286 
3287 
3292 int // O - 0 on success, -1 on error
3293 Fl_Help_View::load(const char *f)// I - Filename to load (may also have target)
3294 {
3295  FILE *fp; // File to read from
3296  long len; // Length of file
3297  char *target; // Target in file
3298  char *slash; // Directory separator
3299  const char *localname; // Local filename
3300  char error[1024]; // Error buffer
3301  char newname[FL_PATH_MAX]; // New filename buffer
3302 
3303  // printf("load(%s)\n",f); fflush(stdout);
3304 
3305  if (strncmp(f, "ftp:", 4) == 0 ||
3306  strncmp(f, "http:", 5) == 0 ||
3307  strncmp(f, "https:", 6) == 0 ||
3308  strncmp(f, "ipp:", 4) == 0 ||
3309  strncmp(f, "mailto:", 7) == 0 ||
3310  strncmp(f, "news:", 5) == 0) {
3311  char urimsg[FL_PATH_MAX];
3312  if ( fl_open_uri(f, urimsg, sizeof(urimsg)) == 0 ) {
3313  clear_selection();
3314 
3315  strlcpy(newname, f, sizeof(newname));
3316  if ((target = strrchr(newname, '#')) != NULL)
3317  *target++ = '\0';
3318 
3319  if (link_)
3320  localname = (*link_)(this, newname);
3321  else
3322  localname = filename_;
3323 
3324  if (!localname)
3325  return (0);
3326 
3327  free_data();
3328 
3329  strlcpy(filename_, newname, sizeof(filename_));
3330  strlcpy(directory_, newname, sizeof(directory_));
3331 
3332  // Note: We do not support Windows backslashes, since they are illegal
3333  // in URLs...
3334  if ((slash = strrchr(directory_, '/')) == NULL)
3335  directory_[0] = '\0';
3336  else if (slash > directory_ && slash[-1] != '/')
3337  *slash = '\0';
3338 
3339  snprintf(error, sizeof(error),
3340  "<HTML><HEAD><TITLE>Error</TITLE></HEAD>"
3341  "<BODY><H1>Error</H1>"
3342  "<P>Unable to follow the link \"%s\" - "
3343  "%s.</P></BODY>",
3344  f, urimsg);
3345  value(error);
3346  //return(-1);
3347  }
3348  return(0);
3349  }
3350 
3351  clear_selection();
3352 
3353  strlcpy(newname, f, sizeof(newname));
3354  if ((target = strrchr(newname, '#')) != NULL)
3355  *target++ = '\0';
3356 
3357  if (link_)
3358  localname = (*link_)(this, newname);
3359  else
3360  localname = filename_;
3361 
3362  if (!localname)
3363  return (0);
3364 
3365  free_data();
3366 
3367  strlcpy(filename_, newname, sizeof(filename_));
3368  strlcpy(directory_, newname, sizeof(directory_));
3369 
3370  // Note: We do not support Windows backslashes, since they are illegal
3371  // in URLs...
3372  if ((slash = strrchr(directory_, '/')) == NULL)
3373  directory_[0] = '\0';
3374  else if (slash > directory_ && slash[-1] != '/')
3375  *slash = '\0';
3376 
3377  if (strncmp(localname, "file:", 5) == 0)
3378  localname += 5; // Adjust for local filename...
3379 
3380  if ((fp = fl_fopen(localname, "rb")) != NULL)
3381  {
3382  fseek(fp, 0, SEEK_END);
3383  len = ftell(fp);
3384  rewind(fp);
3385 
3386  value_ = (const char *)calloc(len + 1, 1);
3387  if (fread((void *)value_, 1, len, fp)==0) { /* use default 0 */ }
3388  fclose(fp);
3389  }
3390  else
3391  {
3392  snprintf(error, sizeof(error),
3393  "<HTML><HEAD><TITLE>Error</TITLE></HEAD>"
3394  "<BODY><H1>Error</H1>"
3395  "<P>Unable to follow the link \"%s\" - "
3396  "%s.</P></BODY>",
3397  localname, strerror(errno));
3398  value_ = strdup(error);
3399  }
3400 
3401  initial_load = 1;
3402  format();
3403  initial_load = 0;
3404 
3405  if (target)
3406  topline(target);
3407  else
3408  topline(0);
3409 
3410  return (0);
3411 }
3412 
3413 
3416 void
3417 Fl_Help_View::resize(int xx, // I - New left position
3418  int yy, // I - New top position
3419  int ww, // I - New width
3420  int hh) // I - New height
3421 {
3422  Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
3423  // Box to draw...
3424 
3425 
3426  Fl_Widget::resize(xx, yy, ww, hh);
3427 
3428  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
3429  scrollbar_.resize(x() + w() - scrollsize - Fl::box_dw(b) + Fl::box_dx(b),
3430  y() + Fl::box_dy(b), scrollsize, h() - scrollsize - Fl::box_dh(b));
3432  y() + h() - scrollsize - Fl::box_dh(b) + Fl::box_dy(b),
3433  w() - scrollsize - Fl::box_dw(b), scrollsize);
3434 
3435  format();
3436 }
3437 
3438 
3443 void
3444 Fl_Help_View::topline(const char *n) // I - Target name
3445 {
3446  Fl_Help_Target key, // Target name key
3447  *target; // Pointer to matching target
3448 
3449 
3450  if (ntargets_ == 0)
3451  return;
3452 
3453  strlcpy(key.name, n, sizeof(key.name));
3454 
3455  target = (Fl_Help_Target *)bsearch(&key, targets_, ntargets_, sizeof(Fl_Help_Target),
3457 
3458  if (target != NULL)
3459  topline(target->y);
3460 }
3461 
3462 
3470 void
3471 Fl_Help_View::topline(int top) // I - Top line number
3472 {
3473  if (!value_)
3474  return;
3475 
3476  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
3477  if (size_ < (h() - scrollsize) || top < 0)
3478  top = 0;
3479  else if (top > size_)
3480  top = size_;
3481 
3482  topline_ = top;
3483 
3484  scrollbar_.value(topline_, h() - scrollsize, 0, size_);
3485 
3486  do_callback();
3487 
3488  redraw();
3489 }
3490 
3491 
3499 void
3500 Fl_Help_View::leftline(int left) // I - Left position
3501 {
3502  if (!value_)
3503  return;
3504 
3505  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
3506  if (hsize_ < (w() - scrollsize) || left < 0)
3507  left = 0;
3508  else if (left > hsize_)
3509  left = hsize_;
3510 
3511  leftline_ = left;
3512 
3513  hscrollbar_.value(leftline_, w() - scrollsize, 0, hsize_);
3514 
3515  redraw();
3516 }
3517 
3518 
3526 void
3527 Fl_Help_View::value(const char *val) // I - Text to view
3528 {
3529  clear_selection();
3530  free_data();
3531  set_changed();
3532 
3533  if (!val)
3534  return;
3535 
3536  value_ = strdup(val);
3537 
3538  initial_load = 1;
3539  format();
3540  initial_load = 0;
3541 
3542  topline(0);
3543  leftline(0);
3544 }
3545 
3546 
3547 /* Returns the Unicode Code Point associated with a quoted character
3548  (aka "HTML Entity").
3549 
3550  Possible encoding formats:
3551  - &name; named entity
3552  - &#nn..; numeric (decimal) Unicode Code Point
3553  - &#xnn..; numeric (hexadecimal) Unicode Code Point
3554  - &#Xnn..; numeric (hexadecimal) Unicode Code Point
3555  'nn..' = decimal or hexadecimal number, resp.
3556 
3557  Contents of the table names[] below:
3558 
3559  All printable ASCII (32-126) and ISO-8859-1 (160-255) characters
3560  are encoded with the same value in Unicode. Special characters
3561  outside the range [0-255] are encoded with their Unicode Code Point
3562  as hexadecimal constants. Example:
3563  - Euro sign: (Unicode) U+20ac = (hex) 0x20ac
3564 
3565  Note: Converted to correct Unicode values and tested (compared with
3566  the display of Firefox). AlbrechtS, 14 Feb. 2016.
3567 
3568  Note to devs: if you add or remove items to/from this list, please
3569  update the documentation in FL/Fl_Help_View.H.
3570 */
3571 static int // O - Code or -1 on error
3572 quote_char(const char *p) { // I - Quoted string
3573  int i; // Looping var
3574  static const struct {
3575  const char *name;
3576  int namelen;
3577  int code;
3578  } *nameptr, // Pointer into name array
3579  names[] = { // Quoting names
3580  { "Aacute;", 7, 193 },
3581  { "aacute;", 7, 225 },
3582  { "Acirc;", 6, 194 },
3583  { "acirc;", 6, 226 },
3584  { "acute;", 6, 180 },
3585  { "AElig;", 6, 198 },
3586  { "aelig;", 6, 230 },
3587  { "Agrave;", 7, 192 },
3588  { "agrave;", 7, 224 },
3589  { "amp;", 4, '&' },
3590  { "Aring;", 6, 197 },
3591  { "aring;", 6, 229 },
3592  { "Atilde;", 7, 195 },
3593  { "atilde;", 7, 227 },
3594  { "Auml;", 5, 196 },
3595  { "auml;", 5, 228 },
3596  { "brvbar;", 7, 166 },
3597  { "bull;", 5, 0x2022 },
3598  { "Ccedil;", 7, 199 },
3599  { "ccedil;", 7, 231 },
3600  { "cedil;", 6, 184 },
3601  { "cent;", 5, 162 },
3602  { "copy;", 5, 169 },
3603  { "curren;", 7, 164 },
3604  { "deg;", 4, 176 },
3605  { "divide;", 7, 247 },
3606  { "Eacute;", 7, 201 },
3607  { "eacute;", 7, 233 },
3608  { "Ecirc;", 6, 202 },
3609  { "ecirc;", 6, 234 },
3610  { "Egrave;", 7, 200 },
3611  { "egrave;", 7, 232 },
3612  { "ETH;", 4, 208 },
3613  { "eth;", 4, 240 },
3614  { "Euml;", 5, 203 },
3615  { "euml;", 5, 235 },
3616  { "euro;", 5, 0x20ac },
3617  { "frac12;", 7, 189 },
3618  { "frac14;", 7, 188 },
3619  { "frac34;", 7, 190 },
3620  { "gt;", 3, '>' },
3621  { "Iacute;", 7, 205 },
3622  { "iacute;", 7, 237 },
3623  { "Icirc;", 6, 206 },
3624  { "icirc;", 6, 238 },
3625  { "iexcl;", 6, 161 },
3626  { "Igrave;", 7, 204 },
3627  { "igrave;", 7, 236 },
3628  { "iquest;", 7, 191 },
3629  { "Iuml;", 5, 207 },
3630  { "iuml;", 5, 239 },
3631  { "laquo;", 6, 171 },
3632  { "lt;", 3, '<' },
3633  { "macr;", 5, 175 },
3634  { "micro;", 6, 181 },
3635  { "middot;", 7, 183 },
3636  { "nbsp;", 5, ' ' },
3637  { "not;", 4, 172 },
3638  { "Ntilde;", 7, 209 },
3639  { "ntilde;", 7, 241 },
3640  { "Oacute;", 7, 211 },
3641  { "oacute;", 7, 243 },
3642  { "Ocirc;", 6, 212 },
3643  { "ocirc;", 6, 244 },
3644  { "Ograve;", 7, 210 },
3645  { "ograve;", 7, 242 },
3646  { "ordf;", 5, 170 },
3647  { "ordm;", 5, 186 },
3648  { "Oslash;", 7, 216 },
3649  { "oslash;", 7, 248 },
3650  { "Otilde;", 7, 213 },
3651  { "otilde;", 7, 245 },
3652  { "Ouml;", 5, 214 },
3653  { "ouml;", 5, 246 },
3654  { "para;", 5, 182 },
3655  { "permil;", 7, 0x2030 },
3656  { "plusmn;", 7, 177 },
3657  { "pound;", 6, 163 },
3658  { "quot;", 5, '\"' },
3659  { "raquo;", 6, 187 },
3660  { "reg;", 4, 174 },
3661  { "sect;", 5, 167 },
3662  { "shy;", 4, 173 },
3663  { "sup1;", 5, 185 },
3664  { "sup2;", 5, 178 },
3665  { "sup3;", 5, 179 },
3666  { "szlig;", 6, 223 },
3667  { "THORN;", 6, 222 },
3668  { "thorn;", 6, 254 },
3669  { "times;", 6, 215 },
3670  { "trade;", 6, 0x2122 },
3671  { "Uacute;", 7, 218 },
3672  { "uacute;", 7, 250 },
3673  { "Ucirc;", 6, 219 },
3674  { "ucirc;", 6, 251 },
3675  { "Ugrave;", 7, 217 },
3676  { "ugrave;", 7, 249 },
3677  { "uml;", 4, 168 },
3678  { "Uuml;", 5, 220 },
3679  { "uuml;", 5, 252 },
3680  { "Yacute;", 7, 221 },
3681  { "yacute;", 7, 253 },
3682  { "yen;", 4, 165 },
3683  { "Yuml;", 5, 0x0178 },
3684  { "yuml;", 5, 255 }
3685  };
3686 
3687  if (!strchr(p, ';')) return -1;
3688  if (*p == '#') {
3689  if (*(p+1) == 'x' || *(p+1) == 'X') return strtol(p+2, NULL, 16);
3690  else return atoi(p+1);
3691  }
3692  for (i = (int)(sizeof(names) / sizeof(names[0])), nameptr = names; i > 0; i --, nameptr ++)
3693  if (strncmp(p, nameptr->name, nameptr->namelen) == 0)
3694  return nameptr->code;
3695 
3696  return -1;
3697 }
3698 
3699 
3701 static void
3703 {
3704  ((Fl_Help_View *)(s->parent()))->topline(int(((Fl_Scrollbar*)s)->value()));
3705 }
3706 
3707 
3709 static void
3711 {
3712  ((Fl_Help_View *)(s->parent()))->leftline(int(((Fl_Scrollbar*)s)->value()));
3713 }
3714 
3715 
3716 //
3717 // End of "$Id$".
3718 //
HV_Edit_Buffer::size
int size()
Definition: Fl_Help_View.cxx:314
Fl_Help_View::initfont
void initfont(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c)
Definition: Fl_Help_View.H:253
Fl_Pixmap.H
fl_width
FL_EXPORT double fl_width(const char *txt)
Definition: fl_font.cxx:65
Fl_Widget::y
int y() const
Definition: Fl_Widget.H:289
Fl_Help_View::select_all
void select_all()
Definition: Fl_Help_View.cxx:2933
Fl_Help_View::find_link
Fl_Help_Link * find_link(int, int)
Definition: Fl_Help_View.cxx:2856
Fl_Help_View::load
int load(const char *f)
Definition: Fl_Help_View.cxx:3293
DEBUG_FUNCTION
#define DEBUG_FUNCTION(L, F)
Definition: Fl_Help_View.cxx:278
Fl_Help_View::selected
static int selected
Definition: Fl_Help_View.H:243
buf
static char * buf
Definition: fl_encoding_mac_roman.cxx:76
FL_HELVETICA_BOLD
const Fl_Font FL_HELVETICA_BOLD
Helvetica (or Arial) bold.
Definition: Enumerations.H:880
fl_getcwd
char * fl_getcwd(char *buf, int maxlen)
Definition: fl_utf8.cxx:699
fl_line
void fl_line(int x, int y, int x1, int y1)
Definition: fl_draw.H:223
Fl_Scrollbar
Definition: Fl_Scrollbar.H:43
fl_rectf
void fl_rectf(int x, int y, int w, int h)
Definition: fl_draw.H:206
Fl_Help_View::draw
void draw()
Definition: Fl_Help_View.cxx:644
FL_META
#define FL_META
One of the meta/Windows keys is down.
Definition: Enumerations.H:563
Fl_Widget::draw_box
void draw_box() const
Definition: fl_boxtype.cxx:442
Fl_Help_View::link_
Fl_Help_Func * link_
Link transform function.
Definition: Fl_Help_View.H:217
fl_margins::current
int current()
Definition: Fl_Help_View.cxx:156
SEEK_END
#define SEEK_END
Definition: zconf.h:486
Fl_Help_Func
const typedef char *() Fl_Help_Func(Fl_Widget *, const char *)
Fl_Help_View::format_table
void format_table(int *table_width, int *columns, const char *table)
Definition: Fl_Help_View.cxx:2068
Fl_Color
unsigned int Fl_Color
Definition: Enumerations.H:934
fl_margins::depth_
int depth_
Definition: Fl_Help_View.cxx:144
Fl_Group::end
void end()
Definition: Fl_Group.cxx:75
Fl_Help_Block::w
int w
Definition: Fl_Help_View.H:56
FL_UNFOCUS
Definition: Enumerations.H:288
Fl_Help_View::hv_selection_color
static Fl_Color hv_selection_color
Definition: Fl_Help_View.H:249
FL_ITALIC
const Fl_Font FL_ITALIC
add this to helvetica, courier, or times
Definition: Enumerations.H:898
broken_xpm
static const char *const broken_xpm[]
Definition: Fl_Help_View.cxx:102
Fl_Image::h
void h(int H)
Definition: Fl_Image.H:80
Fl_Help_View::textcolor_
Fl_Color textcolor_
Text color.
Definition: Fl_Help_View.H:205
HV_Edit_Buffer::~HV_Edit_Buffer
~HV_Edit_Buffer()
Definition: Fl_Help_View.cxx:462
Fl_Widget::show
virtual void show()
Definition: Fl_Widget.cxx:271
Fl::box_dx
static int box_dx(Fl_Boxtype)
Definition: fl_boxtype.cxx:360
Fl_Boxtype
Fl_Boxtype
Definition: Enumerations.H:603
fl_rgb_color
Fl_Color fl_rgb_color(uchar r, uchar g, uchar b)
Definition: Enumerations.H:997
Fl_Help_View::CENTER
Definition: Fl_Help_View.H:202
HV_Edit_Buffer::extend_
int extend_
Definition: Fl_Help_View.cxx:303
HV_Edit_Buffer::add
const char * add(const char *text, int size=-1)
Definition: Fl_Help_View.cxx:365
fl_descent
int fl_descent()
Definition: fl_draw.H:533
quote_char
static int quote_char(const char *)
Definition: Fl_Help_View.cxx:3572
Fl::event_state
static int event_state()
Definition: Fl.H:704
FL_CURSOR_DEFAULT
Definition: Enumerations.H:1049
fl_margins::push
int push(int indent)
Definition: Fl_Help_View.cxx:168
fl_color
void fl_color(Fl_Color c)
Definition: fl_draw.H:52
Fl_Help_View::current_view
static Fl_Help_View * current_view
Definition: Fl_Help_View.H:248
Fl_Help_View::atargets_
int atargets_
Allocated targets.
Definition: Fl_Help_View.H:223
Fl_Help_View::Fl_Help_View
Fl_Help_View(int xx, int yy, int ww, int hh, const char *l=0)
Definition: Fl_Help_View.cxx:3215
FL_DRAG
Definition: Enumerations.H:268
FL_SHIFT
#define FL_SHIFT
One of the shift keys is down.
Definition: Enumerations.H:557
Fl::event_is_click
static int event_is_click()
Definition: Fl.H:661
FL_COURIER_ITALIC
const Fl_Font FL_COURIER_ITALIC
Courier italic.
Definition: Enumerations.H:885
x.H
Fl_Help_View::directory_
char directory_[2048]
Directory for current file.
Definition: Fl_Help_View.H:227
Fl_Help_View::current_pos
static int current_pos
Definition: Fl_Help_View.H:247
filename.H
FL_TIMES
const Fl_Font FL_TIMES
Times roman.
Definition: Enumerations.H:887
free
void free()
Fl_Help_View::scrollbar_size_
int scrollbar_size_
Size for both scrollbars.
Definition: Fl_Help_View.H:229
H
static int H
Definition: Fl_Tooltip.cxx:76
Fl_Help_View::format
void format()
Definition: Fl_Help_View.cxx:1260
Fl_Shared_Image::draw
virtual void draw(int X, int Y, int W, int H, int cx, int cy)
Definition: Fl_Shared_Image.cxx:370
offset
static double offset[5]
Definition: fl_rounded_box.cxx:32
FL_BLUE
const Fl_Color FL_BLUE
Definition: Enumerations.H:960
fl_height
int fl_height()
Definition: fl_draw.H:527
Fl_Help_View::do_align
int do_align(Fl_Help_Block *block, int line, int xx, int a, int &l)
Definition: Fl_Help_View.cxx:605
Fl_Help_View::get_length
int get_length(const char *l)
Definition: Fl_Help_View.cxx:2838
Fl_Widget::x
int x() const
Definition: Fl_Widget.H:284
NULL
#define NULL
Definition: forms.H:34
Fl_Help_View::get_color
Fl_Color get_color(const char *n, Fl_Color c)
Definition: Fl_Help_View.cxx:2681
Fl_Help_View::alinks_
int alinks_
Allocated links.
Definition: Fl_Help_View.H:219
FL_COURIER
const Fl_Font FL_COURIER
Courier normal.
Definition: Enumerations.H:883
fl_draw
FL_EXPORT void fl_draw(const char *str, int x, int y)
Definition: fl_font.cxx:70
Fl_Help_View::get_image
Fl_Shared_Image * get_image(const char *name, int W, int H)
Definition: Fl_Help_View.cxx:2781
Fl_Help_View::size_
int size_
Total document length.
Definition: Fl_Help_View.H:229
Fl_Help_View::begin_selection
char begin_selection()
Definition: Fl_Help_View.cxx:2951
Fl_Widget::do_callback
void do_callback()
Definition: Fl_Widget.H:861
Fl_Help_View::hv_draw
void hv_draw(const char *t, int x, int y, int entity_extra_length=0)
Definition: Fl_Help_View.cxx:238
fl_contrast
Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg)
Definition: fl_color.cxx:435
FL_LEAVE
Definition: Enumerations.H:259
Fl_Help_View::filename_
char filename_[2048]
Current filename.
Definition: Fl_Help_View.H:228
Fl::event_key
static int event_key()
Definition: Fl.H:723
Fl_Image::w
void w(int W)
Definition: Fl_Image.H:76
initial_load
static char initial_load
Definition: Fl_Help_View.cxx:96
fl_fopen
FILE * fl_fopen(const char *f, const char *mode)
Definition: fl_utf8.cxx:498
Fl_Help_Block::border
uchar border
Definition: Fl_Help_View.H:54
b
long b
Definition: jpegint.h:397
key
int key
Definition: Fl_Text_Editor.cxx:91
snprintf
#define snprintf
Definition: flstring.h:64
Fl_Help_Block::y
int y
Definition: Fl_Help_View.H:56
fl_margins
Definition: Fl_Help_View.cxx:143
CMD
#define CMD(a, b, c, d)
Definition: Fl_Help_View.cxx:3035
Fl_Help_Block::start
const char * start
Definition: Fl_Help_View.H:52
Fl::event_x
static int event_x()
Definition: Fl.H:598
Fl_Help_Block::bgcolor
Fl_Color bgcolor
Definition: Fl_Help_View.H:55
Fl::box_dh
static int box_dh(Fl_Boxtype)
Definition: fl_boxtype.cxx:397
FL_HORIZONTAL
#define FL_HORIZONTAL
The valuator can work horizontally.
Definition: Fl_Valuator.H:31
Fl_Help_View.H
Fl_Help_View::extend_selection
char extend_selection()
Definition: Fl_Help_View.cxx:2972
Fl_Widget::w
int w() const
Definition: Fl_Widget.H:294
FL_FOREGROUND_COLOR
const Fl_Color FL_FOREGROUND_COLOR
the default foreground color (0) used for labels and text
Definition: Enumerations.H:937
Fl_Help_Target
Definition: Fl_Help_View.H:130
needspace
static int needspace
Definition: file.cxx:54
Fl::box_dw
static int box_dw(Fl_Boxtype)
Definition: fl_boxtype.cxx:391
math.h
Fl_Window.H
Fl_Help_View::get_attr
const char * get_attr(const char *p, const char *n, char *buf, int bufsize)
Definition: Fl_Help_View.cxx:2609
Fl_Help_Block::end
const char * end
Definition: Fl_Help_View.H:52
FL_CURSOR_INSERT
Definition: Enumerations.H:1053
Fl_Widget::color
Fl_Color color() const
Definition: Fl_Widget.H:378
Fl_Help_View::nlinks_
int nlinks_
Number of links.
Definition: Fl_Help_View.H:219
dw
uchar dw
Definition: fl_boxtype.cxx:286
Fl_Help_View::textcolor
Fl_Color textcolor() const
Definition: Fl_Help_View.H:336
p
static menustate * p
Definition: Fl_Menu.cxx:606
FL_CURSOR_HAND
Definition: Enumerations.H:1054
Fl_Widget::w
void w(int v)
Definition: Fl_Widget.H:143
HV_Edit_Buffer::buf_
char * buf_
Definition: Fl_Help_View.cxx:305
dir
static int dir
Definition: fl_draw_image.cxx:67
Fl::box_dy
static int box_dy(Fl_Boxtype)
Definition: fl_boxtype.cxx:385
fl_utf8.h
header for Unicode and UTF-8 character handling
FL_ALT
#define FL_ALT
One of the alt keys is down.
Definition: Enumerations.H:560
command
static unsigned int command(const char *cmd)
Definition: Fl_Help_View.cxx:3018
FL_MOVE
Definition: Enumerations.H:335
MAX_COLUMNS
#define MAX_COLUMNS
Definition: Fl_Help_View.cxx:72
fl_xyline
void fl_xyline(int x, int y, int x1)
Definition: fl_draw.H:255
Fl_Help_View::clear_global_selection
void clear_global_selection()
Definition: Fl_Help_View.cxx:2942
FL_COURIER_BOLD
const Fl_Font FL_COURIER_BOLD
Courier bold.
Definition: Enumerations.H:884
Fl_Help_View::compare_targets
static int compare_targets(const Fl_Help_Target *t0, const Fl_Help_Target *t1)
Definition: Fl_Help_View.cxx:597
FL_PATH_MAX
#define FL_PATH_MAX
Definition: filename.H:38
Fl_Help_View::selection_push_first
static int selection_push_first
Definition: Fl_Help_View.H:239
Fl_Pixmap
Definition: Fl_Pixmap.H:41
FL_HELVETICA
const Fl_Font FL_HELVETICA
Helvetica (or Arial) normal (0)
Definition: Enumerations.H:879
FL_DOWN_BOX
see figure 1
Definition: Enumerations.H:608
Fl_Help_Target::name
char name[32]
Target name.
Definition: Fl_Help_View.H:131
HV_Edit_Buffer::width
int width()
Definition: Fl_Help_View.cxx:321
Fl_Help_View::mouse_x
static int mouse_x
Definition: Fl_Help_View.H:245
Fl_Help_Block::h
int h
Definition: Fl_Help_View.H:56
Fl_Help_View::add_link
void add_link(const char *n, int xx, int yy, int ww, int hh)
Definition: Fl_Help_View.cxx:529
Fl_Shared_Image::find
static Fl_Shared_Image * find(const char *name, int W=0, int H=0)
Definition: Fl_Shared_Image.cxx:479
strlcpy
#define strlcpy
Definition: flstring.h:84
FL_COMMAND
#define FL_COMMAND
An alias for FL_CTRL on WIN32 and X11, or FL_META on MacOS X.
Definition: Enumerations.H:580
Fl_Help_View::RIGHT
Definition: Fl_Help_View.H:202
FL_FOCUS
Definition: Enumerations.H:283
fl_cursor
FL_EXPORT void fl_cursor(Fl_Cursor)
Definition: fl_cursor.cxx:42
Fl_Widget::visible
unsigned int visible() const
Definition: Fl_Widget.H:660
Fl_Help_View::hv_selection_text_color
static Fl_Color hv_selection_text_color
Definition: Fl_Help_View.H:250
FL_SYMBOL
const Fl_Font FL_SYMBOL
Standard symbol font.
Definition: Enumerations.H:891
Fl_Help_View::selection_push_last
static int selection_push_last
Definition: Fl_Help_View.H:240
Fl_Help_View::find
int find(const char *s, int p=0)
Definition: Fl_Help_View.cxx:1193
Fl_Widget::hide
virtual void hide()
Definition: Fl_Widget.cxx:283
Fl_Help_View::title_
char title_[1024]
Title string.
Definition: Fl_Help_View.H:204
Fl_Fontsize
int Fl_Fontsize
Definition: Enumerations.H:906
table
static symbol table[]
Definition: factory.cxx:1109
indent
const char * indent()
Definition: code.cxx:99
Fl_Scrollbar::value
int value() const
Definition: Fl_Scrollbar.H:65
Fl_Help_View::handle
int handle(int)
Definition: Fl_Help_View.cxx:3128
Fl_Help_View::linkcolor_
Fl_Color linkcolor_
Link color.
Definition: Fl_Help_View.H:205
FL_PUSH
Definition: Enumerations.H:236
fl_push_clip
void fl_push_clip(int x, int y, int w, int h)
Definition: fl_draw.H:82
Fl_Help_View::end_selection
void end_selection(int c=0)
Definition: Fl_Help_View.cxx:3037
Fl_Help_View::topline
int topline() const
Definition: Fl_Help_View.H:350
broken_image
static Fl_Pixmap broken_image(broken_xpm)
Fl_Widget::redraw
void redraw()
Definition: Fl.cxx:1782
Fl_Widget
Definition: Fl_Widget.H:101
Fl_Group
Definition: Fl_Group.H:41
scrollbar_callback
static void scrollbar_callback(Fl_Widget *s, void *)
Definition: Fl_Help_View.cxx:3702
Fl_Widget::box
Fl_Boxtype box() const
Definition: Fl_Widget.H:363
HV_Edit_Buffer::check
void check(int size)
Definition: Fl_Help_View.cxx:440
Fl_Widget::h
int h() const
Definition: Fl_Widget.H:299
Fl_Help_View::add_target
void add_target(const char *n, int yy)
Definition: Fl_Help_View.cxx:571
Fl::event_y
static int event_y()
Definition: Fl.H:603
Fl::copy
static void copy(const char *stuff, int len, int destination, const char *type)
Definition: Fl_win32.cxx:680
Fl_Group::init_sizes
void init_sizes()
Definition: Fl_Group.cxx:572
Fl_Widget::h
void h(int v)
Definition: Fl_Widget.H:145
Fl_Help_View::targets_
Fl_Help_Target * targets_
Targets.
Definition: Fl_Help_View.H:225
Fl_Help_Target::y
int y
Y offset of target.
Definition: Fl_Help_View.H:132
fl_margins::pop
int pop()
Definition: Fl_Help_View.cxx:158
FL_SELECTION_COLOR
const Fl_Color FL_SELECTION_COLOR
the default selection/highlight color
Definition: Enumerations.H:940
Fl_Help_View::~Fl_Help_View
~Fl_Help_View()
Definition: Fl_Help_View.cxx:3281
HV_Edit_Buffer::operator[]
char & operator[](int idx)
Definition: Fl_Help_View.cxx:323
Fl_Help_View::bgcolor_
Fl_Color bgcolor_
Background color.
Definition: Fl_Help_View.H:205
Fl_Help_View::hscrollbar_
Fl_Scrollbar hscrollbar_
Horizontal scrollbar.
Definition: Fl_Help_View.H:234
Fl_Help_View::blocks_
Fl_Help_Block * blocks_
Blocks.
Definition: Fl_Help_View.H:215
Fl_Help_View::follow_link
void follow_link(Fl_Help_Link *)
Definition: Fl_Help_View.cxx:2868
FL_BOLD
const Fl_Font FL_BOLD
add this to helvetica, courier, or times
Definition: Enumerations.H:897
HV_Edit_Buffer::clear
void clear()
Definition: Fl_Help_View.cxx:349
Fl_Help_View::selection_drag_first
static int selection_drag_first
Definition: Fl_Help_View.H:241
Fl_Widget::set_changed
void set_changed()
Definition: Fl_Widget.H:786
Fl_Help_View::fstack_
Fl_Help_Font_Stack fstack_
font stack management
Definition: Fl_Help_View.H:212
Fl::scrollbar_size
static int scrollbar_size()
Definition: Fl.cxx:196
HV_Edit_Buffer
Definition: Fl_Help_View.cxx:299
fl_begin_offscreen
void fl_begin_offscreen(Fl_Offscreen gWorld)
fl_pop_clip
void fl_pop_clip()
Definition: fl_draw.H:103
Fl_Group::handle
int handle(int)
Definition: Fl_Group.cxx:147
x
int x
Definition: test.c:73
Fl_Shared_Image::get
static Fl_Shared_Image * get(const char *name, int W=0, int H=0)
Definition: Fl_Shared_Image.cxx:541
Fl_Widget::callback
Fl_Callback_p callback() const
Definition: Fl_Widget.H:561
Fl_Font
int Fl_Font
Definition: Enumerations.H:877
Fl_Help_View::free_data
void free_data()
Definition: Fl_Help_View.cxx:2490
Fl_Help_View::scrollbar_
Fl_Scrollbar scrollbar_
Vertical scrollbar for document.
Definition: Fl_Help_View.H:234
HV_Edit_Buffer::size_
int size_
Definition: Fl_Help_View.cxx:301
Fl_Help_Block::line
int line[32]
Definition: Fl_Help_View.H:60
Fl
Definition: Fl.H:135
FL_BACKGROUND2_COLOR
const Fl_Color FL_BACKGROUND2_COLOR
the default background color for text, list, and valuator widgets
Definition: Enumerations.H:938
Fl_Help_View::resize
void resize(int, int, int, int)
Definition: Fl_Help_View.cxx:3417
Fl_Help_Block
Definition: Fl_Help_View.H:51
hscrollbar_callback
static void hscrollbar_callback(Fl_Widget *s, void *)
Definition: Fl_Help_View.cxx:3710
FL_SHORTCUT
Definition: Enumerations.H:349
dy
uchar dy
Definition: fl_boxtype.cxx:286
fl_margins::clear
int clear()
Definition: Fl_Help_View.cxx:149
y
int y
Definition: test.c:74
Fl_Help_View::clear_selection
void clear_selection()
Definition: Fl_Help_View.cxx:2927
fl_utf8encode
int fl_utf8encode(unsigned ucs, char *buf)
Definition: fl_utf.c:309
Fl_Help_View::LEFT
Definition: Fl_Help_View.H:202
calloc
voidp calloc()
Fl_Help_View::get_align
int get_align(const char *p, int a)
Definition: Fl_Help_View.cxx:2589
Fl_Help_View
Definition: Fl_Help_View.H:200
FL_GRAY
#define FL_GRAY
Definition: Enumerations.H:978
fl_end_offscreen
void fl_end_offscreen()
Fl_Widget::type
uchar type() const
Definition: Fl_Widget.H:274
Fl_Help_View::ntargets_
int ntargets_
Number of targets.
Definition: Fl_Help_View.H:223
f
Fl_Box_Draw_F * f
Definition: fl_boxtype.cxx:285
Fl_Help_View::topline_
int topline_
Top line in document.
Definition: Fl_Help_View.H:229
HV_Edit_Buffer::HV_Edit_Buffer
HV_Edit_Buffer(int alloc=1024, int ext=1024)
Definition: Fl_Help_View.cxx:334
Fl_Widget::parent
Fl_Group * parent() const
Definition: Fl_Widget.H:254
Fl_Offscreen
CGContextRef Fl_Offscreen
Definition: mac.H:45
malloc
voidp malloc()
fl_create_offscreen
Fl_Offscreen fl_create_offscreen(int w, int h)
Fl_Help_View::nblocks_
int nblocks_
Number of blocks/paragraphs.
Definition: Fl_Help_View.H:213
Fl_Help_Font_Stack::top
void top(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c)
Definition: Fl_Help_View.H:107
HV_Edit_Buffer::allocated_
int allocated_
Definition: Fl_Help_View.cxx:302
fl_margins::margins_
int margins_[100]
Definition: Fl_Help_View.cxx:145
flstring.h
FL_BACKGROUND_COLOR
const Fl_Color FL_BACKGROUND_COLOR
Definition: Enumerations.H:949
Fl_Help_View::selection_drag_last
static int selection_drag_last
Definition: Fl_Help_View.H:242
Fl_Help_View::add_block
Fl_Help_Block * add_block(const char *s, int xx, int yy, int ww, int hh, uchar border=0)
Definition: Fl_Help_View.cxx:489
Fl_Help_View::value
const char * value() const
Definition: Fl_Help_View.H:356
Fl_Help_View::hsize_
int hsize_
Maximum document width.
Definition: Fl_Help_View.H:229
Fl_Help_View::ablocks_
int ablocks_
Allocated blocks.
Definition: Fl_Help_View.H:213
Fl_Help_View::textfont_
Fl_Font textfont_
Default font for text.
Definition: Fl_Help_View.H:209
Fl_Widget::resize
virtual void resize(int x, int y, int w, int h)
Definition: Fl_Widget.cxx:150
strlcat
#define strlcat
Definition: flstring.h:79
fl_margins::fl_margins
fl_margins()
Definition: Fl_Help_View.cxx:147
Fl_Help_View::value_
const char * value_
HTML text value.
Definition: Fl_Help_View.H:211
Fl_Help_View::draw_mode
static int draw_mode
Definition: Fl_Help_View.H:244
Fl_Help_View::pushfont
void pushfont(Fl_Font f, Fl_Fontsize s)
Definition: Fl_Help_View.H:254
FL_RELEASE
Definition: Enumerations.H:244
code
Definition: inftrees.h:24
Fl_Help_View::selection_last
static int selection_last
Definition: Fl_Help_View.H:238
start
static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy, int &X, int &Y, int &W, int &H)
Definition: Fl_Image.cxx:655
Fl_Help_View::leftline_
int leftline_
Lefthand position.
Definition: Fl_Help_View.H:229
fl_help_view_buffer
static Fl_Offscreen fl_help_view_buffer
Definition: Fl_Help_View.cxx:219
uchar
unsigned char uchar
Definition: fl_types.h:30
Fl_Help_Block::x
int x
Definition: Fl_Help_View.H:56
Fl_Help_View::mouse_y
static int mouse_y
Definition: Fl_Help_View.H:246
name
static const char * name
Definition: Fl_arg.cxx:53
FL_CTRL
#define FL_CTRL
One of the ctrl keys is down.
Definition: Enumerations.H:559
Fl_Help_View::selection_first
static int selection_first
Definition: Fl_Help_View.H:237
Fl_Help_View::textsize_
Fl_Fontsize textsize_
Default font size.
Definition: Fl_Help_View.H:210
dh
uchar dh
Definition: fl_boxtype.cxx:286
Fl_Shared_Image
Definition: Fl_Shared_Image.H:50
Fl_Group::draw_child
void draw_child(Fl_Widget &widget) const
Definition: Fl_Group.cxx:768
Fl_Help_View::leftline
int leftline() const
Definition: Fl_Help_View.H:353
FL_ENTER
Definition: Enumerations.H:253
dx
uchar dx
Definition: fl_boxtype.cxx:286
compare_func_t
int(* compare_func_t)(const void *, const void *)
Definition: Fl_Help_View.cxx:80
Fl_Help_View::links_
Fl_Help_Link * links_
Links.
Definition: Fl_Help_View.H:221
Fl_Help_View::defcolor_
Fl_Color defcolor_
Default text color.
Definition: Fl_Help_View.H:205
Fl_Help_View::popfont
void popfont(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c)
Definition: Fl_Help_View.H:256
Fl_Shared_Image::release
void release()
Definition: Fl_Shared_Image.cxx:230
Fl_Valuator::step
void step(int a)
Definition: Fl_Valuator.H:106
fl_open_uri
int fl_open_uri(const char *uri, char *msg, int msglen)
Definition: fl_open_uri.cxx:98
HV_Edit_Buffer::c_str
char * c_str()
Definition: Fl_Help_View.cxx:312
error
static void error(const char *format,...)
Definition: Fl_abort.cxx:66
fl_rect
void fl_rect(int x, int y, int w, int h)
Definition: fl_draw.H:201
HV_Edit_Buffer::cmp
int cmp(const char *str)
Definition: Fl_Help_View.cxx:320