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