Annotation of libwww/Library/src/HTStyle.c, revision 2.10.2.1

2.10      frystyk     1: /*                                                                   HTStyle.c
                      2: **     STYLE IMPLEMENTATION FOR HYPERTEXT
                      3: **
                      4: **     (c) COPYRIGHT CERN 1994.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
1.1       timbl       6: **
                      7: **     Styles allow the translation between a logical property
                      8: **     of a piece of text and its physical representation.
                      9: **
                     10: **     A StyleSheet is a collection of styles, defining the
                     11: **     translation necessary to
                     12: **     represent a document. It is a linked list of styles.
                     13: */
2.10.2.1! frystyk    14: 
        !            15: /* Library include files */
        !            16: #include "tcp.h"
1.1       timbl      17: #include "HTUtils.h"
2.10.2.1! frystyk    18: #include "HTString.h"
        !            19: #include "HTStyle.h"
1.1       timbl      20: 
2.7       timbl      21: 
                     22: /*     Local definition of style
                     23: **     -------------------------
                     24: */
                     25: /*      The Style Structure
                     26: **      -------------------
                     27: */
                     28: 
                     29: typedef float HTCoord;
                     30: typedef int HTColor;
                     31: 
                     32: typedef struct {
                     33:     short               kind;           /* only NX_LEFTTAB implemented*/
                     34:     HTCoord             position;       /* x coordinate for stop */
                     35: } HTTabStop;
                     36: 
                     37: 
                     38: struct _HTStyle {
                     39: 
                     40: /*      Style management information
                     41: */
                     42:     struct _HTStyle     *next;          /* Link for putting into stylesheet */
                     43:     char *              name;           /* Style name */
                     44:     char *              SGMLTag;        /* Tag name to start */
                     45: 
                     46: 
                     47: /*      Character attributes    (a la NXRun)
                     48: */
                     49:     HTFont              font;           /* Font id */
                     50:     HTCoord             fontSize;       /* The size of font, not independent */
                     51:     HTColor             color;  /* text gray of current run */
                     52:     int                 superscript;    /* superscript (-sub) in points */
                     53: 
                     54:     HTAnchor            *anchor;        /* Anchor id if any, else zero */
                     55: 
                     56: /*      Paragraph Attribtes     (a la NXTextStyle)
                     57: */
                     58:     HTCoord             indent1st;      /* how far first line in paragraph is
                     59:                                  * indented */
                     60:     HTCoord             leftIndent;     /* how far second line is indented */
                     61:     HTCoord             rightIndent;    /* (Missing from NeXT version */
                     62:     short               alignment;      /* quad justification */
                     63:     HTCoord             lineHt;         /* line height */
                     64:     HTCoord             descentLine;    /* descender bottom from baseline */
                     65:     HTTabStop           *tabs;          /* array of tab stops, 0 terminated */
                     66: 
                     67:     BOOL                wordWrap;       /* Yes means wrap at space not char */
                     68:     BOOL                freeFormat;     /* Yes means \n is just white space */
                     69:     HTCoord             spaceBefore;    /* Omissions from NXTextStyle */
                     70:     HTCoord             spaceAfter;
                     71:     int                 paraFlags;      /* Paragraph flags, bits as follows: */
                     72: 
                     73: #define PARA_KEEP       1       /* Do not break page within this paragraph */
                     74: #define PARA_WITH_NEXT  2       /* Do not break page after this paragraph */
                     75: 
                     76: #define HT_JUSTIFY 0            /* For alignment */
                     77: #define HT_LEFT 1
                     78: #define HT_RIGHT 2
                     79: #define HT_CENTER 3
                     80: };
                     81: 
                     82: 
1.1       timbl      83: /*     Create a new style
                     84: */
                     85: PUBLIC HTStyle* HTStyleNew NOARGS
                     86: {
2.7       timbl      87:     return (HTStyle *)calloc(1, sizeof(HTStyle));
1.1       timbl      88: }
                     89: 
                     90: /*     Create a new style with a name
                     91: */
                     92: PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
                     93: {
                     94:     HTStyle * self = HTStyleNew();
                     95:     StrAllocCopy(self->name, name);
                     96:     return self;
                     97: }
                     98: 
                     99: 
                    100: /*     Free a style
                    101: */
                    102: PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self)
                    103: {
                    104:     if (self->name) free(self->name);
                    105:     if (self->SGMLTag) free(self->SGMLTag);
                    106:     free(self);
                    107:     return 0;
                    108: }
                    109: 
                    110: 
                    111: #ifdef SUPPRESS  /* Only on the NeXT */
                    112: /*     Read a style from a stream      (without its name)
                    113: **     --------------------------
                    114: **
                    115: **     Reads a style with paragraph information from a stream.
                    116: **     The style name is not read or written by these routines.
                    117: */
                    118: #define NONE_STRING "(None)"
                    119: #define HTStream NXStream
                    120: 
                    121: HTStyle * HTStyleRead (HTStyle * style, HTStream * stream)
                    122: {
                    123:     char myTag[STYLE_NAME_LENGTH];
                    124:     char fontName[STYLE_NAME_LENGTH];
                    125:     NXTextStyle *p;
                    126:     int        tab;
                    127:     int gotpara;               /* flag: have we got a paragraph definition? */
                    128:        
                    129:     NXScanf(stream, "%s%s%f%d",
                    130:        myTag,
                    131:        fontName,
                    132:        &style->fontSize,
                    133:        &gotpara);
                    134:     if (gotpara) {
                    135:        if (!style->paragraph) {
                    136:            style->paragraph = malloc(sizeof(*(style->paragraph)));
                    137:            style->paragraph->tabs = 0;
                    138:        }
                    139:        p = style->paragraph;
                    140:        NXScanf(stream, "%f%f%f%f%hd%f%f%hd",
                    141:            &p->indent1st,
                    142:            &p->indent2nd,
                    143:            &p->lineHt,
                    144:            &p->descentLine,
                    145:            &p->alignment,
                    146:            &style->spaceBefore,
                    147:            &style->spaceAfter,
                    148:            &p->numTabs);
                    149:        if (p->tabs) free(p->tabs);
                    150:        p->tabs = malloc(p->numTabs * sizeof(p->tabs[0]));
                    151:        for (tab=0; tab < p->numTabs; tab++) {
                    152:            NXScanf(stream, "%hd%f",
                    153:                    &p->tabs[tab].kind,
                    154:                    &p->tabs[tab].x);
                    155:        }
                    156:     } else { /* No paragraph */
                    157:         if (style->paragraph) {
                    158:            free(style->paragraph);
                    159:            style->paragraph = 0;
                    160:        }
                    161:     } /* if no paragraph */
                    162:     StrAllocCopy(style->SGMLTag, myTag);
                    163:     if (strcmp(fontName, NONE_STRING)==0)
                    164:         style->font = 0;
                    165:     else
                    166:         style->font = [Font newFont:fontName size:style->fontSize];
                    167:     return 0;
                    168: 
                    169: }
                    170: 
                    171: 
                    172: /*     Write a style to a stream in a compatible way
                    173: */
                    174: HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream)
                    175: {
                    176:     int tab;
                    177:     NXTextStyle *p = style->paragraph;
                    178:     NXPrintf(stream, "%s %s %f %d\n",
                    179:        style->SGMLTag,
                    180:        style->font ? [style->font name] : NONE_STRING,
                    181:        style->fontSize,
                    182:        p!=0);
                    183: 
                    184:     if (p) {
                    185:        NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n",
                    186:            p->indent1st,
                    187:            p->indent2nd,
                    188:            p->lineHt,
                    189:            p->descentLine,
                    190:            p->alignment,
                    191:            style->spaceBefore,
                    192:            style->spaceAfter,
                    193:            p->numTabs);
                    194:            
                    195:        for (tab=0; tab < p->numTabs; tab++)
                    196:            NXPrintf(stream, "\t%d %f\n",
                    197:                    p->tabs[tab].kind,
                    198:                    p->tabs[tab].x);
                    199:        }
                    200:     return style;
                    201: }
                    202: 
                    203: 
                    204: /*     Write a style to stdout for diagnostics
                    205: */
                    206: HTStyle * HTStyleDump (HTStyle * style)
                    207: {
                    208:     int tab;
                    209:     NXTextStyle *p = style->paragraph;
                    210:     printf("Style %d `%s' SGML:%s. Font %s %.1f point.\n",
                    211:        style,
                    212:        style->name,
                    213:        style->SGMLTag,
                    214:        [style->font name],
                    215:        style->fontSize);
                    216:     if (p) {
                    217:         printf(
                    218:        "\tIndents: first=%.0f others=%.0f, Height=%.1f Desc=%.1f\n"
                    219:        "\tAlign=%d, %d tabs. (%.0f before, %.0f after)\n",
                    220:            p->indent1st,
                    221:            p->indent2nd,
                    222:            p->lineHt,
                    223:            p->descentLine,
                    224:            p->alignment,
                    225:            p->numTabs,
                    226:            style->spaceBefore,
                    227:            style->spaceAfter);
                    228:            
                    229:        for (tab=0; tab < p->numTabs; tab++) {
                    230:            printf("\t\tTab kind=%d at %.0f\n",
                    231:                    p->tabs[tab].kind,
                    232:                    p->tabs[tab].x);
                    233:        }
                    234:        printf("\n");
                    235:     } /* if paragraph */
                    236:     return style;
                    237: }
                    238: #endif
                    239: 
                    240: 
                    241: /*                     StyleSheet Functions
                    242: **                     ====================
                    243: */
                    244: 
                    245: /*     Searching for styles:
                    246: */
                    247: HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name)
                    248: {
                    249:     HTStyle * scan;
2.8       howcome   250: 
                    251:     if (!self) {       /* added by HWL 11/8/94 */
2.10.2.1! frystyk   252:        if (TRACE) fprintf(TDEST, "HTStyleNamed.. Called with NULL pointer\n");
2.9       frystyk   253:        return NULL;
2.8       howcome   254:     }
                    255: 
1.1       timbl     256:     for (scan=self->styles; scan; scan=scan->next)
                    257:         if (0==strcmp(scan->name, name)) return scan;
2.10.2.1! frystyk   258:     if (TRACE) fprintf(TDEST, "StyleSheet: No style named `%s'\n", name);
2.9       frystyk   259:     return NULL;
1.1       timbl     260: }
                    261: 
                    262: #ifdef NEXT_SUPRESS            /* Not in general common code */
                    263: 
                    264: HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style)
                    265: {
                    266:     HTStyle * scan;
                    267:     for (scan=self->styles; scan; scan=scan->next)
                    268:         if (scan->paragraph == para) return scan;
                    269:     return 0;
                    270: }
                    271: 
                    272: /*     Find the style which best fits a given run
                    273: **     ------------------------------------------
                    274: **
                    275: **     This heuristic is used for guessing the style for a run of
                    276: **     text which has been pasted in. In order, we try:
                    277: **
                    278: **     A style whose paragraph structure is actually used by the run.
                    279: **     A style matching in font
                    280: **     A style matching in paragraph style exactly
                    281: **     A style matching in paragraph to a degree
                    282: */
                    283: 
                    284: HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run)
                    285: {
                    286:     HTStyle * scan;
                    287:     HTStyle * best = 0;
                    288:     int        bestMatch = 0;
                    289:     NXTextStyle * rp = run->paraStyle;
                    290:     for (scan=self->styles; scan; scan=scan->next)
                    291:         if (scan->paragraph == run->paraStyle) return scan;    /* Exact */
                    292: 
                    293:     for (scan=self->styles; scan; scan=scan->next){
                    294:        NXTextStyle * sp = scan->paragraph;
                    295:        if (sp) {
                    296:            int match = 0;
                    297:            if (sp->indent1st ==        rp->indent1st)  match = match+1;
                    298:            if (sp->indent2nd ==        rp->indent2nd)  match = match+2;
                    299:            if (sp->lineHt ==           rp->lineHt)     match = match+1;
                    300:            if (sp->numTabs ==          rp->numTabs)    match = match+1;
                    301:            if (sp->alignment ==        rp->alignment)  match = match+3;
                    302:            if (scan->font ==           run->font)      match = match+10;
                    303:            if (match>bestMatch) {
                    304:                    best=scan;
                    305:                    bestMatch=match;
                    306:            }
                    307:        }
                    308:     }
2.10.2.1! frystyk   309:     if (TRACE) fprintf(TDEST, "HTStyleForRun: Best match for style is %d out of 18\n",
1.1       timbl     310:                         bestMatch);
                    311:     return best;
                    312: }
                    313: #endif
                    314: 
                    315: 
                    316: /*     Add a style to a sheet
                    317: **     ----------------------
                    318: */
                    319: HTStyleSheet * HTStyleSheetAddStyle ARGS2
                    320:   (HTStyleSheet *,self, HTStyle *,style)
                    321: {
                    322:     style->next = 0;           /* The style will go on the end */
                    323:     if (!self->styles) {
                    324:        self->styles = style;
                    325:     } else {
                    326:        HTStyle * scan;
                    327:         for(scan=self->styles; scan->next; scan=scan->next); /* Find end */
                    328:        scan->next=style;
                    329:     }
                    330:     return self;
                    331: }
                    332: 
                    333: 
                    334: /*     Remove the given object from a style sheet if it exists
                    335: */
                    336: HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
                    337:   (HTStyleSheet *,self, HTStyle *,style)
                    338: {
2.6       luotonen  339:     if (self->styles == style) {
1.1       timbl     340:        self->styles = style->next;
                    341:        return self;
                    342:     } else {
                    343:        HTStyle * scan;
                    344:        for(scan = self->styles; scan; scan = scan->next) {
2.6       luotonen  345:            if (scan->next == style) {
1.1       timbl     346:                scan->next = style->next;
                    347:                return self;
                    348:            }
                    349:        }
                    350:     }
                    351:     return 0;
                    352: }
                    353: 
                    354: /*     Create new style sheet
                    355: */
                    356: 
                    357: HTStyleSheet * HTStyleSheetNew NOARGS
                    358: {
                    359:     HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self));
                    360: 
                    361:     memset((void*)self, 0, sizeof(*self));     /* ANSI */
                    362: /* Harbison c ref man says (char*)self
                    363:    but k&r ansii and abc books and Think_C say (void*) */
                    364:     
                    365: /*    bzero(self, sizeof(*self)); */           /* BSD */
                    366:     return self;
                    367: }
                    368: 
                    369: 
                    370: /*     Free off a style sheet pointer
                    371: */
                    372: HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self)
                    373: {
                    374:     HTStyle * style;
                    375:     while((style=self->styles)!=0) {
                    376:         self->styles = style->next;
                    377:        HTStyleFree(style);
                    378:     }
                    379:     free(self);
                    380:     return 0;
                    381: }
                    382: 
                    383: 
                    384: /*     Read a stylesheet from a typed stream
                    385: **     -------------------------------------
                    386: **
                    387: **     Reads a style sheet from a stream.  If new styles have the same names
                    388: **     as existing styles, they replace the old ones without changing the ids.
                    389: */
                    390: 
                    391: #ifdef NEXT_SUPRESS  /* Only on the NeXT */
                    392: HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream)
                    393: {
                    394:     int numStyles;
                    395:     int i;
                    396:     HTStyle * style;
                    397:     char styleName[80];
                    398:     NXScanf(stream, " %d ", &numStyles);
2.10.2.1! frystyk   399:     if (TRACE) fprintf(TDEST, "Stylesheet: Reading %d styles\n", numStyles);
1.1       timbl     400:     for (i=0; i<numStyles; i++) {
                    401:         NXScanf(stream, "%s", styleName);
                    402:         style = HTStyleNamed(self, styleName);
                    403:        if (!style) {
                    404:            style = HTStyleNewNamed(styleName);
                    405:            (void) HTStyleSheetAddStyle(self, style);
                    406:        }
                    407:        (void) HTStyleRead(style, stream);
                    408:        if (TRACE) HTStyleDump(style);
                    409:     }
                    410:     return self;
                    411: }
                    412: 
                    413: /*     Write a stylesheet to a typed stream
                    414: **     ------------------------------------
                    415: **
                    416: **     Writes a style sheet to a stream.
                    417: */
                    418: 
                    419: HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream)
                    420: {
                    421:     int numStyles = 0;
                    422:     HTStyle * style;
                    423:     
                    424:     for(style=self->styles; style; style=style->next) numStyles++;
                    425:     NXPrintf(stream, "%d\n", numStyles);
                    426:     
2.10.2.1! frystyk   427:     if (TRACE) fprintf(TDEST, "StyleSheet: Writing %d styles\n", numStyles);
1.1       timbl     428:     for (style=self->styles; style; style=style->next) {
                    429:         NXPrintf(stream, "%s ", style->name);
                    430:        (void) HTStyleWrite(style, stream);
                    431:     }
                    432:     return self;
                    433: }
                    434: #endif

Webmaster