~ubuntu-branches/ubuntu/edgy/lynx/edgy

« back to all changes in this revision

Viewing changes to WWW/Library/Implementation/HTStyle.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-16 12:14:10 UTC
  • Revision ID: james.westby@ubuntu.com-20040916121410-cz1gu92c4nqfeyrg
Tags: upstream-2.8.5
ImportĀ upstreamĀ versionĀ 2.8.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      Style Implementation for Hypertext                      HTStyle.c
 
2
**      ==================================
 
3
**
 
4
**      Styles allow the translation between a logical property
 
5
**      of a piece of text and its physical representation.
 
6
**
 
7
**      A StyleSheet is a collection of styles, defining the
 
8
**      translation necessary to
 
9
**      represent a document.  It is a linked list of styles.
 
10
*/
 
11
 
 
12
#include <HTUtils.h>
 
13
#include <HTStyle.h>
 
14
 
 
15
#include <LYLeaks.h>
 
16
 
 
17
/*      Create a new style
 
18
*/
 
19
PUBLIC HTStyle* HTStyleNew NOARGS
 
20
{
 
21
    HTStyle * self = typecalloc(HTStyle);
 
22
    if (self == NULL)
 
23
        outofmem(__FILE__, "HTStyleNew");
 
24
    return self;
 
25
}
 
26
 
 
27
/*      Create a new style with a name
 
28
*/
 
29
PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
 
30
{
 
31
    HTStyle * self = HTStyleNew();
 
32
    StrAllocCopy(self->name, name);
 
33
    self->id = -1; /* <0 */
 
34
    return self;
 
35
}
 
36
 
 
37
 
 
38
/*      Free a style
 
39
*/
 
40
PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self)
 
41
{
 
42
    FREE(self->name);
 
43
    FREE(self->SGMLTag);
 
44
    FREE(self);
 
45
    return NULL;
 
46
}
 
47
 
 
48
 
 
49
#ifdef SUPPRESS  /* Only on the NeXT */
 
50
/*      Read a style from a stream      (without its name)
 
51
**      --------------------------
 
52
**
 
53
**      Reads a style with paragraph information from a stream.
 
54
**      The style name is not read or written by these routines.
 
55
*/
 
56
#define NONE_STRING "(None)"
 
57
#define HTStream NXStream
 
58
 
 
59
HTStyle * HTStyleRead (HTStyle * style, HTStream * stream)
 
60
{
 
61
    char myTag[STYLE_NAME_LENGTH];
 
62
    char fontName[STYLE_NAME_LENGTH];
 
63
    NXTextStyle *p;
 
64
    int tab;
 
65
    int gotpara;                /* flag: have we got a paragraph definition? */
 
66
 
 
67
    NXScanf(stream, "%s%s%f%d",
 
68
        myTag,
 
69
        fontName,
 
70
        &style->fontSize,
 
71
        &gotpara);
 
72
    if (gotpara) {
 
73
        if (!style->paragraph) {
 
74
            style->paragraph = malloc(sizeof(*(style->paragraph)));
 
75
            if (!style->paragraph)
 
76
                outofmem(__FILE__, "HTStyleRead");
 
77
            style->paragraph->tabs = 0;
 
78
        }
 
79
        p = style->paragraph;
 
80
        NXScanf(stream, "%f%f%f%f%hd%f%f%hd",
 
81
            &p->indent1st,
 
82
            &p->indent2nd,
 
83
            &p->lineHt,
 
84
            &p->descentLine,
 
85
            &p->alignment,
 
86
            &style->spaceBefore,
 
87
            &style->spaceAfter,
 
88
            &p->numTabs);
 
89
        FREE(p->tabs);
 
90
        p->tabs = malloc(p->numTabs * sizeof(p->tabs[0]));
 
91
        if (!p->tabs)
 
92
            outofmem(__FILE__, "HTStyleRead");
 
93
        for (tab=0; tab < p->numTabs; tab++) {
 
94
            NXScanf(stream, "%hd%f",
 
95
                    &p->tabs[tab].kind,
 
96
                    &p->tabs[tab].x);
 
97
        }
 
98
    } else { /* No paragraph */
 
99
        FREE(style->paragraph);
 
100
    } /* if no paragraph */
 
101
    StrAllocCopy(style->SGMLTag, myTag);
 
102
    if (strcmp(fontName, NONE_STRING)==0)
 
103
        style->font = 0;
 
104
    else
 
105
        style->font = [Font newFont:fontName size:style->fontSize];
 
106
    return NULL;
 
107
}
 
108
 
 
109
 
 
110
/*      Write a style to a stream in a compatible way
 
111
*/
 
112
HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream)
 
113
{
 
114
    int tab;
 
115
    NXTextStyle *p = style->paragraph;
 
116
    NXPrintf(stream, "%s %s %f %d\n",
 
117
        style->SGMLTag,
 
118
        style->font ? [style->font name] : NONE_STRING,
 
119
        style->fontSize,
 
120
        p!=0);
 
121
 
 
122
    if (p) {
 
123
        NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n",
 
124
            p->indent1st,
 
125
            p->indent2nd,
 
126
            p->lineHt,
 
127
            p->descentLine,
 
128
            p->alignment,
 
129
            style->spaceBefore,
 
130
            style->spaceAfter,
 
131
            p->numTabs);
 
132
 
 
133
        for (tab=0; tab < p->numTabs; tab++)
 
134
            NXPrintf(stream, "\t%d %f\n",
 
135
                    p->tabs[tab].kind,
 
136
                    p->tabs[tab].x);
 
137
        }
 
138
    return style;
 
139
}
 
140
 
 
141
 
 
142
/*      Write a style to stdout for diagnostics
 
143
*/
 
144
HTStyle * HTStyleDump (HTStyle * style)
 
145
{
 
146
    int tab;
 
147
    NXTextStyle *p = style->paragraph;
 
148
    printf(STYLE_DUMP_FONT,
 
149
        style,
 
150
        style->name,
 
151
        style->SGMLTag,
 
152
        [style->font name],
 
153
        style->fontSize);
 
154
    if (p) {
 
155
        printf(STYLE_DUMP_IDENT,
 
156
            p->indent1st,
 
157
            p->indent2nd,
 
158
            p->lineHt,
 
159
            p->descentLine);
 
160
        printf(STYLE_DUMP_ALIGN,
 
161
            p->alignment,
 
162
            p->numTabs,
 
163
            style->spaceBefore,
 
164
            style->spaceAfter);
 
165
 
 
166
        for (tab=0; tab < p->numTabs; tab++) {
 
167
            printf(STYLE_DUMP_TAB,
 
168
                    p->tabs[tab].kind,
 
169
                    p->tabs[tab].x);
 
170
        }
 
171
        printf("\n");
 
172
    } /* if paragraph */
 
173
    return style;
 
174
}
 
175
#endif /* SUPPRESS */
 
176
 
 
177
 
 
178
/*                      StyleSheet Functions
 
179
**                      ====================
 
180
*/
 
181
 
 
182
/*      Searching for styles:
 
183
*/
 
184
HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name)
 
185
{
 
186
    HTStyle * scan;
 
187
    for (scan=self->styles; scan; scan=scan->next)
 
188
        if (0==strcmp(scan->name, name)) return scan;
 
189
    CTRACE((tfp, "StyleSheet: No style named `%s'\n", name));
 
190
    return NULL;
 
191
}
 
192
 
 
193
#ifdef NEXT_SUPRESS             /* Not in general common code */
 
194
 
 
195
HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style)
 
196
{
 
197
    HTStyle * scan;
 
198
    for (scan=self->styles; scan; scan=scan->next)
 
199
        if (scan->paragraph == para) return scan;
 
200
    return NULL;
 
201
}
 
202
 
 
203
/*      Find the style which best fits a given run
 
204
**      ------------------------------------------
 
205
**
 
206
**      This heuristic is used for guessing the style for a run of
 
207
**      text which has been pasted in.  In order, we try:
 
208
**
 
209
**      A style whose paragraph structure is actually used by the run.
 
210
**      A style matching in font
 
211
**      A style matching in paragraph style exactly
 
212
**      A style matching in paragraph to a degree
 
213
*/
 
214
 
 
215
HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run)
 
216
{
 
217
    HTStyle * scan;
 
218
    HTStyle * best = 0;
 
219
    int bestMatch = 0;
 
220
    NXTextStyle * rp = run->paraStyle;
 
221
    for (scan=self->styles; scan; scan=scan->next)
 
222
        if (scan->paragraph == run->paraStyle) return scan;     /* Exact */
 
223
 
 
224
    for (scan=self->styles; scan; scan=scan->next){
 
225
        NXTextStyle * sp = scan->paragraph;
 
226
        if (sp) {
 
227
            int match = 0;
 
228
            if (sp->indent1st ==        rp->indent1st)  match = match+1;
 
229
            if (sp->indent2nd ==        rp->indent2nd)  match = match+2;
 
230
            if (sp->lineHt ==           rp->lineHt)     match = match+1;
 
231
            if (sp->numTabs ==          rp->numTabs)    match = match+1;
 
232
            if (sp->alignment ==        rp->alignment)  match = match+3;
 
233
            if (scan->font ==           run->font)      match = match+10;
 
234
            if (match>bestMatch) {
 
235
                    best=scan;
 
236
                    bestMatch=match;
 
237
            }
 
238
        }
 
239
    }
 
240
    CTRACE((tfp, "HTStyleForRun: Best match for style is %d out of 18\n",
 
241
                 bestMatch));
 
242
    return best;
 
243
}
 
244
#endif /* NEXT_SUPRESS */
 
245
 
 
246
 
 
247
/*      Add a style to a sheet
 
248
**      ----------------------
 
249
*/
 
250
HTStyleSheet * HTStyleSheetAddStyle ARGS2
 
251
  (HTStyleSheet *,self, HTStyle *,style)
 
252
{
 
253
    style->next = 0;            /* The style will go on the end */
 
254
    if (!self->styles) {
 
255
        self->styles = style;
 
256
    } else {
 
257
        HTStyle * scan;
 
258
        for(scan=self->styles; scan->next; scan=scan->next); /* Find end */
 
259
        scan->next=style;
 
260
    }
 
261
    return self;
 
262
}
 
263
 
 
264
 
 
265
/*      Remove the given object from a style sheet if it exists
 
266
*/
 
267
HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
 
268
  (HTStyleSheet *,self, HTStyle *,style)
 
269
{
 
270
    if (self->styles == style) {
 
271
        self->styles = style->next;
 
272
        return self;
 
273
    } else {
 
274
        HTStyle * scan;
 
275
        for(scan = self->styles; scan; scan = scan->next) {
 
276
            if (scan->next == style) {
 
277
                scan->next = style->next;
 
278
                return self;
 
279
            }
 
280
        }
 
281
    }
 
282
    return NULL;
 
283
}
 
284
 
 
285
/*      Create new style sheet
 
286
*/
 
287
 
 
288
HTStyleSheet * HTStyleSheetNew NOARGS
 
289
{
 
290
    HTStyleSheet * self = typecalloc(HTStyleSheet);
 
291
    if (self == NULL)
 
292
        outofmem(__FILE__, "HTStyleSheetNew");
 
293
    return self;
 
294
}
 
295
 
 
296
 
 
297
/*      Free off a style sheet pointer
 
298
*/
 
299
HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self)
 
300
{
 
301
    HTStyle * style;
 
302
    while((style=self->styles)!=0) {
 
303
        self->styles = style->next;
 
304
        HTStyleFree(style);
 
305
    }
 
306
    FREE(self);
 
307
    return NULL;
 
308
}
 
309
 
 
310
 
 
311
/*      Read a stylesheet from a typed stream
 
312
**      -------------------------------------
 
313
**
 
314
**      Reads a style sheet from a stream.  If new styles have the same names
 
315
**      as existing styles, they replace the old ones without changing the ids.
 
316
*/
 
317
 
 
318
#ifdef NEXT_SUPRESS  /* Only on the NeXT */
 
319
HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream)
 
320
{
 
321
    int numStyles;
 
322
    int i;
 
323
    HTStyle * style;
 
324
    char styleName[80];
 
325
    NXScanf(stream, " %d ", &numStyles);
 
326
    CTRACE((tfp, "Stylesheet: Reading %d styles\n", numStyles));
 
327
    for (i=0; i<numStyles; i++) {
 
328
        NXScanf(stream, "%s", styleName);
 
329
        style = HTStyleNamed(self, styleName);
 
330
        if (!style) {
 
331
            style = HTStyleNewNamed(styleName);
 
332
            (void) HTStyleSheetAddStyle(self, style);
 
333
        }
 
334
        (void) HTStyleRead(style, stream);
 
335
        if (TRACE) HTStyleDump(style);
 
336
    }
 
337
    return self;
 
338
}
 
339
 
 
340
/*      Write a stylesheet to a typed stream
 
341
**      ------------------------------------
 
342
**
 
343
**      Writes a style sheet to a stream.
 
344
*/
 
345
 
 
346
HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream)
 
347
{
 
348
    int numStyles = 0;
 
349
    HTStyle * style;
 
350
 
 
351
    for(style=self->styles; style; style=style->next) numStyles++;
 
352
    NXPrintf(stream, "%d\n", numStyles);
 
353
 
 
354
    CTRACE((tfp, "StyleSheet: Writing %d styles\n", numStyles));
 
355
    for (style=self->styles; style; style=style->next) {
 
356
        NXPrintf(stream, "%s ", style->name);
 
357
        (void) HTStyleWrite(style, stream);
 
358
    }
 
359
    return self;
 
360
}
 
361
#endif /* NEXT_SUPRESS */