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