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