Merge branch 'master' of https://git.maemo.org/projects/erwise
[erwise] / HText / HText.c
1 /*
2  * HText.c --
3  *
4  * Author: Teemu Rantanen <tvr@cs.hut.fi>
5  * Copyright (c) 1992 Teemu Rantanen
6  *                    All rights reserved
7  *
8  * Created: Wed Feb 26 15:59:04 1992 tvr
9  * Last modified: Mon Apr 27 00:41:22 1992 tvr
10  *
11  */
12
13 #include <stdio.h>
14
15 #include "HTStyle.h"
16 #include "HText.h"
17
18
19 /*
20  * This file interacts with WWWLibrary and builds one hypertext page.
21  * For every hypertext object on this page will be set
22  *  - data, length
23  *  - anchor information
24  *  - style
25  * Empty object will be generated for paragraph endings, newlines and
26  * tabulators.
27  */
28
29
30 /*
31  * Debug module (temporary)
32  */
33
34 #define HT_DEBUG(a)             /*printf a*/
35
36
37 /*
38  * Local prototype
39  */
40
41 void new_htext_object ();
42 void make_paragraph_object ();
43 void HText_setStyle ();
44
45
46 /*
47  * Local text (temporary)
48  */
49
50 struct HText *HtLocalText;
51
52
53 /*
54  * When constructing data, save it first here. Then malloc needed space
55  * and copy it
56  */
57
58 char localdata[HTEXT_MAX_OBJECT_SIZE];
59
60
61 /*
62  * Set same anchor information to all objects belonging to same
63  * anchor.
64  */
65
66 HTChildAnchor *local_anchor = 0;
67
68 /*
69  * Default style
70  */
71 extern HTStyleSheet *styleSheet;
72
73
74 /*
75  * This file has functions that WWWLibrary uses to construct an hypertext
76  * object.
77  */
78
79 /*                      Creation Method
80 **                      ---------------
81 */
82 struct HText *
83 HText_new (anchor)
84      HTParentAnchor *anchor;
85 {
86   struct HText *self;
87
88   /*
89    * Create hypertext object.
90    */
91
92   self = (struct HText *) malloc (sizeof (struct HText));
93
94   if (!self)
95     return self;
96
97   HTAnchor_setDocument (anchor, (HyperDoc *) self);
98
99   /*
100    * Initialize object.
101    */
102
103   memset (self, 0, sizeof (struct HText));
104
105   /*
106    * Set some WWWLibrary stuff ...
107    */
108   self->node_anchor = anchor;
109
110   /*
111    * Setup hashing code
112    */
113
114   HtLocalText = self;
115
116   return self;
117 }
118
119
120 /*      Free Entire Text
121 **      ----------------
122 */
123 void 
124 HText_free (self)
125      struct HText *self;
126 {
127   struct HTextObject *p, *p2;
128   struct HTextAnchor *a, *a2;
129
130   if (!self)
131     return;
132
133   p = self->first;
134
135   /*
136    * Set some WWWLibrary stuff ...
137    */
138   if (self->node_anchor)
139     HTAnchor_setDocument (self->node_anchor, (HyperDoc *) 0);
140
141
142   /*
143    * Free all data allocated on this file.
144    */
145   while (p)
146     {
147       p2 = p;
148       p = p->next;
149
150       /*
151        * Avoid loop if something goes wrong
152        */
153       p2->next = p2->prev = NULL;
154
155       if (p2->data)
156         free (p2->data);
157
158       free (p2);
159
160     }
161
162   a = self->anchorlist;
163
164   while (a)
165     {
166       a2 = a;
167       a = a->next;
168
169       free (a2);
170     }
171
172   free (self);
173 }
174
175 /*
176  * Get default style
177  */
178 HTStyle *
179 ht_get_default_style ()
180 {
181   HTStyle *p = styleSheet->styles;
182
183   while (p && p->next)
184     {
185       if (!strcmp (p->SGMLTag, "XMP"))
186         return p;
187       p = p->next;
188     }
189
190   /*
191    * Return last if xmp not found
192    */
193   return p;
194 }
195
196
197
198 /*                      Object Building methods
199 **                      -----------------------
200 **
201 **      These are used by a parser to build the text in an object
202 */
203 void 
204 HText_beginAppend (text)
205      struct HText *text;
206 {
207   /*
208    * Set object to accept text
209    */
210
211   new_htext_object (text);
212
213   if (!text->first)
214     {
215       HT_DEBUG ((stderr, "htext begin append failed?\n"));
216     }
217
218   /*
219    * Set default style. Some pages cause no setStyle.
220    */
221   HText_setStyle (text, ht_get_default_style ());
222 }
223
224
225 /*      New paragraph in current style
226 **      ------------------------------
227 ** See also: setStyle.
228 */
229
230 void 
231 HText_appendParagraph (text)
232      struct HText *text;
233 {
234   HT_DEBUG (("\nHText_appendParagraph\n"));
235
236   /*
237    * Create paragraph object
238    */
239
240   make_paragraph_object (text, HTEXT_PARAGRAPH);
241 }
242
243
244
245
246 /*      Append a character to the text object
247 **      -------------------------------------
248 */
249 void 
250 HText_appendCharacter (text, ch)
251      struct HText *text;
252      char ch;
253 {
254   struct HTextObject *p;
255   int l;
256   static char lastchar = 0;
257
258   HT_DEBUG (("%c", ch));
259
260   /*
261    * safety
262    */
263
264   if (!text)
265     return;
266
267   /*
268    * Parse special characters
269    */
270   if (ch == '\n')
271     {
272
273       make_paragraph_object (text, HTEXT_NEWLINE);
274
275       return;
276
277     }
278
279   if (ch == '\t')
280     {
281
282       make_paragraph_object (text, HTEXT_TAB);
283
284       return;
285
286     }
287
288   /*
289    * Append space(s) at the end of objects
290    */
291   if (lastchar == ' ' && ch != ' ')
292     {
293
294       new_htext_object (text);
295
296       /*
297        * Don't loose this character
298        */
299       lastchar = ch;
300
301       HText_appendCharacter (text, ch);
302
303       return;
304     }
305
306   lastchar = ch;
307
308   p = text->last;
309
310   /*
311    * If local buffer is full, make continued hypertext object.
312    * This should not happen (is extreamely rare).
313    */
314
315   if (p->length >= HTEXT_MAX_OBJECT_SIZE)
316     {
317
318       p->paragraph = HTEXT_CONTINUE;
319
320       new_htext_object (text);
321
322       HText_appendCharacter (p, ch);
323
324       /* return */
325
326     }
327   else
328     {
329
330       localdata[p->length++] = ch;
331     }
332 }
333
334
335 HTextAnchor_t *
336 htext_new_anchor ()
337 {
338   HTextAnchor_t *p;
339
340   p = (HTextAnchor_t *) malloc (sizeof (HTextAnchor_t));
341
342   if (!p)
343     {
344       HT_DEBUG (("cannot malloc on htext_new_anchor(). tough.\n"));
345
346       exit (-1);
347     }
348
349   memset (p, 0, sizeof (HTextAnchor_t));
350
351   return p;
352 }
353
354
355 /*              Anchor handling
356 **              ---------------
357 */
358 /*      Start an anchor field
359 */
360 void 
361 HText_beginAnchor (text, anc)
362      struct HText *text;
363      HTChildAnchor *anc;
364 {
365   HT_DEBUG (("\nHText_beginAnchor [%s]\n", anc->tag));
366
367   /*
368    * Set up anchor
369    */
370
371   if (!anc)
372     return;
373
374   if (HTAnchor_followMainLink ((HTAnchor *) anc))
375     {
376       /*
377        * Anchor is to be shown on the screen
378        */
379       new_htext_object (text);
380
381       local_anchor = anc;
382     }
383   /*
384    * Anchor is HREF anchor only
385    */
386   if (!text->anchorlist)
387     {
388
389       text->anchorlist = htext_new_anchor ();
390
391       text->anchorlist->object = text->last;
392
393       text->anchorlist->anchor = anc;
394
395     }
396   else
397     {
398
399       HTextAnchor_t *p = text->anchorlist;
400
401       for (; p->next; p = p->next) ;
402
403       p->next = htext_new_anchor ();
404
405       p->next->anchor = anc;
406
407       p->next->object = text->last;
408     }
409 }
410
411
412
413 /*
414  * End anchor creation
415  */
416
417 void 
418 HText_endAnchor (text)
419      struct HText *text;
420 {
421   HT_DEBUG (("\nHText_endAnchor\n"));
422
423   /*
424    * Create this anchor an object and create new
425    */
426
427   new_htext_object (text);
428
429   local_anchor = NULL;
430
431 }
432
433
434
435 void 
436 HText_appendText (text, str)
437      struct HText *text;
438      char *str;
439 {
440   register char *p;
441
442   HT_DEBUG (("HText_appendText by characters\n"));
443
444   /*
445    * Append characters (or better, words)
446    */
447
448   for (p = str; *p; p++)
449     HText_appendCharacter (text, *p);
450
451 }
452
453 /*
454  * End text appending
455  */
456
457 void 
458 HText_endAppend (text)
459      struct HText *text;
460 {
461   HT_DEBUG (("HText_endAppend"));
462
463   new_htext_object (text);
464 }
465
466
467 void 
468 HText_setStyle (text, style)
469      struct HText *text;
470      HTStyle *style;
471 {
472   HT_DEBUG (("HText_setStyle %s\n", style->name));
473
474   if (!style)
475     {
476       HT_DEBUG (("HText bug on HText_setStyle ... not changing style\n"));
477       return;
478     }
479
480   /*
481    * Begin style
482    */
483   new_htext_object (text);
484
485   /*
486    * If many headers in a row, append paragraph
487    */
488   if (text->last->style == style)
489     {
490       HText_appendParagraph (text);
491     }
492
493   text->last->style = style;
494 }
495
496
497
498 BOOL 
499 HText_select (text)
500      struct HText *text;
501 {
502   HT_DEBUG (("\nHText_select ??????\n"));
503   /*
504    * Do what ???
505    */
506
507   HtLocalText = text;
508 }
509
510
511
512 BOOL 
513 HText_selectAnchor (text, anchor)
514      struct HText *text;
515      struct HTChildAnchor *anchor;
516 {
517   HT_DEBUG (("\nHText_selectAnchor\n"));
518
519   /*
520    * Something stupid ?
521    */
522 }
523
524
525
526 /*
527  * Allocate new object. Set up modes from previous. Set up data -area.
528  */
529
530 struct HTextObject *
531 malloc_ht_object (prev)
532      struct HTextObject *prev;
533 {
534   struct HTextObject *p;
535
536   /*
537    * New object
538    */
539
540   p = (struct HTextObject *) malloc (sizeof (struct HTextObject));
541
542   if (!p)
543     {
544       HT_DEBUG (("cannot malloc hypertextobject\n"));
545       exit (-1);
546     }
547
548   if (prev)
549     {
550
551       memcpy (p, prev, sizeof (struct HTextObject));
552
553       p->data = 0;
554
555       p->length = 0;
556
557       p->anchor = 0;
558
559       p->paragraph = 0;
560
561     }
562   else
563     {
564
565       memset (p, 0, sizeof (struct HTextObject));
566
567     }
568
569
570   return p;
571 }
572
573
574
575
576 /*
577  * Create new hypertext object.
578  */
579
580 void 
581 new_htext_object (text)
582      struct HText *text;
583 {
584   struct HTextObject *p;
585
586   /*
587    * First object ?
588    */
589   if (text->first == 0)
590     {
591       text->first = text->last = malloc_ht_object (NULL);
592
593       return;
594     }
595
596   /*
597    * Temporary assignment
598    */
599
600   p = text->last;
601
602   /*
603    * Strip all null objects exept paragraph marks
604    */
605   if ((p->length == 0) && !(p->paragraph))
606     return;
607
608   /*
609    * Check paragraph objects
610    */
611   if (p->paragraph && (p->paragraph != HTEXT_CONTINUE) && p->length)
612     {
613       HT_DEBUG (("non null paragraph object ?\n"));
614       exit (-1);
615     }
616
617   /*
618    * If constructing object, malloc and copy local data
619    */
620
621   if (p->length)
622     {
623
624       p->data = (char *) malloc (p->length + 1);
625
626       if (!p->data)
627         {
628           HT_DEBUG (("cannot malloc data on new_htext_object()\n"));
629           exit (-1);
630         }
631
632       memcpy (p->data, localdata, p->length);
633
634       p->data[p->length] = 0;
635     }
636
637   /*
638    * Set anchorinformation to object
639    */
640
641   p->anchor = local_anchor;
642
643   /*
644    * Create new object
645    */
646
647   p = malloc_ht_object (text->last);
648
649   /*
650    * Set it last
651    */
652
653   p->prev = text->last;
654
655   text->last->next = p;
656
657   text->last = p;
658 }
659
660
661
662 /*
663  * Make empty object only stating paragraph, tab or newline
664  */
665
666 void 
667 make_paragraph_object (text, type)
668      struct HText *text;
669      int type;
670 {
671   new_htext_object (text);
672
673   text->last->paragraph = type;
674
675   new_htext_object (text);
676
677 }
678
679
680 /*
681  * Malloc and copy data
682  */
683 char *
684 ht_memdup (data, len)
685      char *data;
686      int len;
687 {
688   char *p;
689
690   p = (char *) malloc (len);
691
692   if (!p)
693     return 0;
694
695   memcpy (p, data, len);
696
697   return p;
698 }
699
700
701 /*
702  * Duplicate object information of this hypertext-page
703  */
704
705 HText_t *
706 HtDuplicate (text)
707      HText_t *text;
708 {
709   HText_t *newtext;
710   HTextObject_t *o, *p;
711   HTextObject_t *p_old = 0;
712
713   newtext = (HText_t *) malloc (sizeof (*newtext));
714
715   if (!newtext)
716     return 0;
717
718   memset (newtext, 0, sizeof (*newtext));
719
720   o = text->first;
721
722   /*
723    * Allocate new htext -page info
724    */
725   if (o)
726     {
727       p = newtext->first = (HTextObject_t *) malloc (sizeof (*p));
728
729       if (!p)
730         {
731
732           free (newtext);
733
734           return 0;
735         }
736     }
737
738   while (o)
739     {
740       memset (p, 0, sizeof (*p));
741
742       p->paragraph = o->paragraph;
743
744       p->length = o->length;
745
746       p->style = o->style;
747
748       p->data = (char *) ht_memdup (o->data, o->length);
749
750       if (!p->data)
751         {
752
753           goto free_allocated_error;
754         }
755
756       p->prev = p_old;
757
758       if (o->next)
759         {
760
761           p_old = p;
762
763           p = (HTextObject_t *) malloc (sizeof (*p));
764
765           if (!p)
766             {
767
768               goto free_allocated_error;
769             }
770
771           p_old->next = p;
772         }
773
774       o = o->next;
775     }
776
777   newtext->last = p;
778
779   return newtext;
780
781 free_allocated_error:
782
783   o = newtext->first;
784
785   while (o)
786     {
787
788       if (o->data)
789         free (o->data);
790
791       free (o);
792     }
793
794   free (newtext);
795
796   return 0;
797 }