1 /* Style Implementation for Hypertext HTStyle.c
2 ** ==================================
4 ** Styles allow the translation between a logical property
5 ** of a piece of text and its physical representation.
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.
16 PUBLIC HTStyle* HTStyleNew NOARGS
18 HTStyle * self = (HTStyle *)malloc(sizeof(*self));
19 memset(self, 0, sizeof(*self));
21 self->color = HT_BLACK;
25 /* Create a new style with a name
27 PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
29 HTStyle * self = HTStyleNew();
30 StrAllocCopy(self->name, name);
37 PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self)
39 if (self->name) free(self->name);
40 if (self->SGMLTag) free(self->SGMLTag);
46 #ifdef SUPPRESS /* Only on the NeXT */
47 /* Read a style from a stream (without its name)
48 ** --------------------------
50 ** Reads a style with paragraph information from a stream.
51 ** The style name is not read or written by these routines.
53 #define NONE_STRING "(None)"
54 #define HTStream NXStream
56 HTStyle * HTStyleRead (HTStyle * style, HTStream * stream)
58 char myTag[STYLE_NAME_LENGTH];
59 char fontName[STYLE_NAME_LENGTH];
62 int gotpara; /* flag: have we got a paragraph definition? */
64 NXScanf(stream, "%s%s%f%d",
70 if (!style->paragraph) {
71 style->paragraph = malloc(sizeof(*(style->paragraph)));
72 style->paragraph->tabs = 0;
75 NXScanf(stream, "%f%f%f%f%hd%f%f%hd",
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",
91 } else { /* No paragraph */
92 if (style->paragraph) {
93 free(style->paragraph);
96 } /* if no paragraph */
97 StrAllocCopy(style->SGMLTag, myTag);
98 if (strcmp(fontName, NONE_STRING)==0)
101 style->font = [Font newFont:fontName size:style->fontSize];
107 /* Write a style to a stream in a compatible way
109 HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream)
112 NXTextStyle *p = style->paragraph;
113 NXPrintf(stream, "%s %s %f %d\n",
115 style->font ? [style->font name] : NONE_STRING,
120 NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n",
130 for (tab=0; tab < p->numTabs; tab++)
131 NXPrintf(stream, "\t%d %f\n",
139 /* Write a style to stdout for diagnostics
141 HTStyle * HTStyleDump (HTStyle * style)
144 NXTextStyle *p = style->paragraph;
145 printf("Style %d `%s' SGML:%s. Font %s %.1f point.\n",
153 "\tIndents: first=%.0f others=%.0f, Height=%.1f Desc=%.1f\n"
154 "\tAlign=%d, %d tabs. (%.0f before, %.0f after)\n",
164 for (tab=0; tab < p->numTabs; tab++) {
165 printf("\t\tTab kind=%d at %.0f\n",
176 /* StyleSheet Functions
177 ** ====================
180 /* Searching for styles:
182 HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name)
185 for (scan=self->styles; scan; scan=scan->next)
186 if (0==strcmp(scan->name, name)) return scan;
187 if (TRACE) printf("StyleSheet: No style named `%s'\n", name);
191 #ifdef NEXT_SUPRESS /* Not in general common code */
193 HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style)
196 for (scan=self->styles; scan; scan=scan->next)
197 if (scan->paragraph == para) return scan;
201 /* Find the style which best fits a given run
202 ** ------------------------------------------
204 ** This heuristic is used for guessing the style for a run of
205 ** text which has been pasted in. In order, we try:
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
213 HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run)
218 NXTextStyle * rp = run->paraStyle;
219 for (scan=self->styles; scan; scan=scan->next)
220 if (scan->paragraph == run->paraStyle) return scan; /* Exact */
222 for (scan=self->styles; scan; scan=scan->next){
223 NXTextStyle * sp = scan->paragraph;
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) {
238 if (TRACE) printf("HTStyleForRun: Best match for style is %d out of 18\n",
245 /* Add a style to a sheet
246 ** ----------------------
248 HTStyleSheet * HTStyleSheetAddStyle ARGS2
249 (HTStyleSheet *,self, HTStyle *,style)
251 style->next = 0; /* The style will go on the end */
253 self->styles = style;
256 for(scan=self->styles; scan->next; scan=scan->next); /* Find end */
263 /* Remove the given object from a style sheet if it exists
265 HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
266 (HTStyleSheet *,self, HTStyle *,style)
268 if (self->styles = style) {
269 self->styles = style->next;
273 for(scan = self->styles; scan; scan = scan->next) {
274 if (scan->next = style) {
275 scan->next = style->next;
283 /* Create new style sheet
286 HTStyleSheet * HTStyleSheetNew NOARGS
288 HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self));
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*) */
294 /* bzero(self, sizeof(*self)); */ /* BSD */
299 /* Free off a style sheet pointer
301 HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self)
304 while((style=self->styles)!=0) {
305 self->styles = style->next;
313 /* Read a stylesheet from a typed stream
314 ** -------------------------------------
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.
320 #ifdef NEXT_SUPRESS /* Only on the NeXT */
321 HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream)
327 NXScanf(stream, " %d ", &numStyles);
328 if (TRACE) printf("Stylesheet: Reading %d styles\n", numStyles);
329 for (i=0; i<numStyles; i++) {
330 NXScanf(stream, "%s", styleName);
331 style = HTStyleNamed(self, styleName);
333 style = HTStyleNewNamed(styleName);
334 (void) HTStyleSheetAddStyle(self, style);
336 (void) HTStyleRead(style, stream);
337 if (TRACE) HTStyleDump(style);
342 /* Write a stylesheet to a typed stream
343 ** ------------------------------------
345 ** Writes a style sheet to a stream.
348 HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream)
353 for(style=self->styles; style; style=style->next) numStyles++;
354 NXPrintf(stream, "%d\n", numStyles);
356 if (TRACE) printf("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);