2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * $XConsortium: FeatureSupport.C /main/43 1996/12/03 18:22:13 rcs $
26 * (c) Copyright 1996 Digital Equipment Corporation.
27 * (c) Copyright 1996 Hewlett-Packard Company.
28 * (c) Copyright 1996 International Business Machines Corp.
29 * (c) Copyright 1996 Sun Microsystems, Inc.
30 * (c) Copyright 1996 Novell, Inc.
31 * (c) Copyright 1996 FUJITSU LIMITED.
32 * (c) Copyright 1996 Hitachi.
45 #define C_WindowSystem
52 #include "FeatureValue.h"
53 #include "StyleSheetExceptions.h"
54 #include <utility/funcs.h>
57 #include <Dt/CanvasP.h>
58 #include "CanvasRenderer.hh"
61 #define HIGHLIGHT_DEBUG
64 #if defined(UseWideChars) && defined(sun) && !defined(SVR4)
65 #define mbstowcs(a,b,c) Xmbstowcs(a,b,c)
66 #define wcstombs(a,b,c) Xwcstombs(a,b,c)
72 int bottom_margin = 0;
74 int point2pixel(int size) {
75 return(XmConvertUnits(window_system().toplevel(), XmHORIZONTAL, XmPOINTS,
80 CanvasRenderer::dofontlist(ElementFeatures&, const FeatureSet&, Symbol**)
82 // This member function needs to be removed from header and herein.
86 CanvasRenderer::dofont(PartialElementFeatures &return_features,
87 const FeatureSet &complete,
90 const Feature *fontfeature = complete.lookup(symbols[FONT]);
91 if (fontfeature == NULL)
94 const FeatureValue* fv = fontfeature->value();
95 assert( fv->type() == FeatureValue::featureset );
97 const FeatureSet* fs = ((FeatureValueFeatureSet*)fv)->value();
98 char* xlfd = _dofont(*fs, symbols);
102 return_features.set_font (xlfd);
108 cerr << "(WARNING) could not resolve font\n";
111 const Feature *subsuperF = fs->lookup(symbols[SUBSUPER]);
113 const char* subsuper = (const char *)*subsuperF->value();
115 if (strcasecmp(subsuper, "sub") == 0 ||
116 strcasecmp(subsuper, "subscript") == 0)
118 return_features.subsuper(PartialElementFeatures::subscript);
120 else if (strcasecmp(subsuper, "super") == 0 ||
121 strcasecmp(subsuper, "superscript") == 0)
123 return_features.subsuper(PartialElementFeatures::superscript);
126 return_features.subsuper(PartialElementFeatures::baseline);
132 CanvasRenderer::get_pattern(const char *fallback, const char *weight, const char *slant, int size)
135 const char *foundry_str = "*";
136 const char *family_str = "*";
137 const char *weight_str = weight;
138 const char *slant_str = slant;
139 const char *setwidth_name_str = "*";
140 const char *style_str = "*";
141 int point_size = size;
142 const char *spacing_str = "*";
143 const char *charset_str = "*-*";
148 // set the display variable based on if we are printing or displaying online
150 if (window_system().printing() == TRUE) {
151 display = window_system().printDisplay();
154 display = window_system().display();
160 fprintf(stderr, "(DEBUG) fallback=\"%s\" is being tried...",
163 char *dupfallback = strdup(fallback);
169 // -dt-application-medium-r-normal-sans-8-80-75-75-p-46-iso8859-1
171 // hack the foundry name from the front of the xlfd
172 ptr = strtok(dupfallback, "-");
180 fprintf(stderr, "(DEBUG)foundry = %s.\n", foundry_str);
185 ptr = strtok(NULL, "-");
193 fprintf(stderr, "(DEBUG)family = %s.\n", family_str);
197 // get weight from fallback string if not specified by
198 // style sheet element
199 ptr = strtok(NULL, "-");
201 // if no more token in fallback pattern is done
206 // if the string is a wildcard then no style sheet weight
207 // was specified so use xlfd field
208 if (weight_str && (strcmp(weight_str, "*") == 0)) {
212 fprintf(stderr, "(DEBUG)weight = %s.\n", weight_str);
216 // get the slant from the fallback string if not specified
217 // by the style sheet element
218 ptr = strtok(NULL, "-");
220 // if no more tokens in fallback then the pattern is done
225 // if the string is a wildcard then no style sheet weight
226 // was specified so use xlfd field
227 if (slant_str && (strcmp(slant_str, "*") == 0)) {
231 fprintf(stderr, "(DEBUG)slant = %s.\n", slant_str);
235 // if slant is specified as ROMAN or ITALIC change to "i" or "r"
236 if (strcasecmp(slant_str, "roman") == 0) {
239 else if (strcasecmp(slant_str, "italic") == 0) {
243 // get the setwidth name from the front of the xlfd
244 ptr = strtok(NULL, "-");
245 // if no more tokens in fallback then the pattern is done
250 fprintf(stderr, "(DEBUG)setwidth = %s.\n", ptr);
254 // get the add style name from the front of the xlfd
255 ptr = strtok(NULL, "-");
256 // if no more tokens in fallback then the pattern is done
264 fprintf(stderr, "(DEBUG)style_str = %s.\n", style_str);
268 // get the pixel size from the front of the xlfd
269 ptr = strtok(NULL, "-");
270 // if no more tokens in fallback then the pattern is done
275 fprintf(stderr, "(DEBUG)pixel size = %s.\n", ptr);
279 // get the point size from the front of the xlfd
280 ptr = strtok(NULL, "-");
282 // make sure there is a token
285 // a point size of -1 indicates that no style sheet size
286 // was specified. in this case, we'll convert the
287 // xlfd field and use that size
289 // ??? should put a check here to make sure ptr is an integer value
290 if (point_size == -1) {
291 point_size = atoi(ptr);
293 point_size = 10 * point_size;
296 fprintf(stderr, "(DEBUG)point size = %d.\n", point_size);
300 // else no more tokens in fallback then the pattern is done
302 // make sure we replace default of -1 with something
303 // before making the pattern
304 if (point_size == -1) {
305 point_size = 140 + (20 * f_font_scale);;
310 // apply scaling factor
311 point_size = point_size + (20 * f_font_scale);
313 // get the resolution x from the front of the xlfd
314 ptr = strtok(NULL, "-");
315 // if no more tokens in fallback then the pattern is done
320 fprintf(stderr, "(DEBUG)x resolution = %s.\n", ptr);
324 // get the resolution y from the front of the xlfd
325 ptr = strtok(NULL, "-");
326 // if no more tokens in fallback then the pattern is done
331 fprintf(stderr, "(DEBUG)y resolution = %s.\n", ptr);
335 // get the spacing from the front of the xlfd
336 ptr = strtok(NULL, "-");
337 // if no more tokens in fallback then the pattern is done
345 fprintf(stderr, "(DEBUG)setwidth = %s.\n", ptr);
349 // get the average width from the front of the xlfd
350 ptr = strtok(NULL, "-");
351 // if no more tokens in fallback then the pattern is done
356 fprintf(stderr, "(DEBUG)average width = %s.\n", ptr);
360 // get the charset registery and encoding
361 // if a font really does include a $ i'm screwed
363 ptr = strtok(NULL, "$");
364 // if no more tokens in fallback then the pattern is done
373 fprintf(stderr, "(DEBUG)charset = %s.\n", charset_str);
379 // -dt-application-medium-r-normal-sans-8-80-75-75-p-46-iso8859-1
382 "-%s-%s-%s-%s-normal-%s-*-%d-*-*-%s-*-%s",
383 foundry_str ? foundry_str : "*",
384 family_str ? family_str : "*",
385 weight_str ? weight_str : "*",
386 slant_str ? slant_str : "*",
387 style_str ? style_str : "*",
389 spacing_str ? spacing_str : "*",
390 charset_str ? charset_str : "*-*"
394 // If the font exists, return a copy
395 if (XLoadQueryFont(display, pattern)) {
397 printf("pattern = %s.\n", pattern);
399 xlfd = strdup(pattern);
403 // determine if the font is a standard application font name
404 if ( (strcmp(foundry_str, "dt") == 0) &&
405 (strcmp(family_str, "application") == 0)) {
407 // round the point size to the nearest match
408 if (point_size < 90 ) point_size = 80;
409 else if (point_size < 110) point_size = 100;
410 else if (point_size < 130) point_size = 120;
411 else if (point_size < 160) point_size = 140;
412 else if (point_size < 210) point_size = 180;
413 else point_size = 240;
416 printf("point size = %d.\n", point_size);
421 "-%s-%s-%s-%s-normal-%s-*-%d-*-*-%s-*-%s",
422 foundry_str ? foundry_str : "*",
423 family_str ? family_str : "*",
424 weight_str ? weight_str : "*",
425 slant_str ? slant_str : "*",
426 style_str ? style_str : "*",
428 spacing_str ? spacing_str : "*",
429 charset_str ? charset_str : "*-*"
432 // If font does not exist, try using the font cache
433 if (XLoadQueryFont(display, pattern)) {
435 printf("pattern = %s.\n", pattern);
437 xlfd = strdup(pattern);
440 } // end if desktop font
443 // if still not found, lookup string in cache.
444 // point_size and scale are extracted first.
446 xlfd = f_fontcache.lookup(family_str,
449 (point_size - (20 * f_font_scale)) / 10,
455 printf("xlfd = %s.\n", xlfd);
462 CanvasRenderer::_dofont(const FeatureSet &fs, Symbol** symbols)
464 const char *fallback = NULL;
466 const Feature *fallbackF = fs.lookup(symbols[FALLBACK]);
468 if (fallback = *fallbackF->value()) {
469 if (strcasecmp(fallback, "sans") == 0)
471 else if (strcasecmp(fallback, "serif") == 0)
473 else if (strcasecmp(fallback, "mono") == 0)
475 else if (strcasecmp(fallback, "symbol") == 0)
476 fallback = f_symbol ;
483 fprintf(stderr, "(DEBUG) fallback=\"%s\"\n", fallback);
485 cerr << "(WARNING) invalid fallback \"" << fallback <<
486 "\" specified." << endl;
490 const Feature *weightF = fs.lookup(symbols[WEIGHT]);
491 const Feature *slantF = fs.lookup(symbols[SLANT]);
492 const Feature *sizeF = fs.lookup(symbols[SIZE]);
494 const char *name = NULL, *foundry = NULL, *charset = NULL;
496 // need to add something for spacing here
497 //const Feature *spacingF = fs.lookup(symbols[SPACING]);
502 for (i = 0; i < fs.entries(); i++) {
505 if ((entry = fs.at(i)) == NULL)
508 if (entry->name() == *symbols[FAMILY]) {
510 const FeatureSet* familyFS;
511 if ((familyFS = *entry->value()) == NULL)
514 // resolve name,foundry,charset
515 const Feature* nameF = familyFS->lookup(symbols[NAME]);
517 name = *nameF->value();
521 cerr << "(WARNING) You need to specify either family name "
522 "or font fallback in stylesheet." << endl;
527 const Feature* foundryF = familyFS->lookup(symbols[FOUNDRY]);
529 foundry = *foundryF->value();
531 const Feature* charsetF = familyFS->lookup(symbols[CHARSET]);
533 charset = *charsetF->value();
536 cerr << "(WARNING) You need to specify charset if you "
537 "specify family name in stylesheet." << endl;
542 assert( name && charset );
544 font = f_fontcache.lookup(name,
545 (const char *)*weightF->value(),
546 (const char *)*slantF->value(),
547 (int)*sizeF->value(),
549 f_font_scale); // scale factor
551 if (font == NULL && fallback) {
555 if ((font = f_fontcache.lookup(name,
556 (const char *)*weightF->value(),
557 (const char *)*slantF->value(),
558 (int)*sizeF->value(),
560 f_font_scale) // scale factor
566 // if xlfd already defined, create a font list
568 xlfd = (char*)realloc(xlfd, strlen(xlfd) + strlen(font) + 3);
572 // otherwise, just dup the font streing
577 } // end if entry name is a font family
579 } // end for each feature support entry
581 // if we have a font definition at this point where almost home
585 // if a comma appears in the xlfd string, then then it is a font
586 // list so append a colon to the end of the font list string
588 if (strchr(xlfd, ',')) {
593 // if no font families were specified, just use what we have from
594 // the fallback and whatever font attributes were specified
598 font = get_pattern(fallback,
599 (const char *)*weightF->value(),
600 (const char *)*slantF->value(),
601 (int)*sizeF->value());
607 // if we still can't find one go with whatever.
610 xlfd = "-*-*-*-*-*-*-*-*-*-*-*-*-*";
613 fprintf(stderr, "resulting in \"%s\".\n", xlfd);
616 } // else if fallback
621 // see if we have a 2 part font family (separated by comma)
622 const char *family = *familyF->value();
623 const char *p = family ;
624 while (*p && (*p != ','))
628 // p points to comma or end of string
631 int len = p - family ;
632 fallback = new char[len + 1] ;
633 strncpy(fallback, family, len);
636 do p++; while (isspace(*p));
642 #ifdef JBM_FONT_DEBUG
643 cerr << "name: " << name << endl;
644 cerr << "foundry: " << foundry << endl;
645 cerr << "charset: " << charset << endl;
647 cerr << "family: (yes)" << endl;
649 cerr << "family: (no)" << endl;
652 cerr << "weight: " << (const char *)*weightF->value() << endl;
654 cerr << "weight: (no)" << endl;
657 cerr << "slant: " << (const char *)*slantF->value() << endl;
659 cerr << "slant: (no)" << endl;
662 cerr << "size: " << (int)*sizeF->value() << endl;
664 cerr << "size: (no)" << endl;
666 cerr << "scale: " << f_font_scale << endl;
667 cerr << "fallback: " << fallback << endl;
670 #if defined FONT_DEBUG || defined FONT_DEBUG_XLFD
672 cerr << "xlfd: " << xlfd << endl;
674 cerr << "xlfd: (nil)" << endl;
681 CanvasRenderer::dounderline(ElementFeatures&, const FeatureSet&, Symbol**)
683 cerr << "dounderline: called " << endl;
686 #ifdef NOTIMPLEMENTED
688 CanvasRenderer::dofooter(ElementFeatures&, const FeatureSet&, Symbol**)
690 cerr << "dofooter: called " << endl;
694 CanvasRenderer::doheader(ElementFeatures&, const FeatureSet&, Symbol**)
696 cerr << "doheader: called " << endl;
701 CanvasRenderer::domedia(ElementFeatures &return_features,
702 const FeatureSet &complete, Symbol **symbols)
704 cerr << "domedia: called " << endl;
706 const FeatureSet *mset = *complete.lookup(symbols[MEDIA])->value();
708 const Feature *orient = mset->lookup(symbols[ORIENTATION]);
712 const char *orientation = *orient->value();
714 if (strcasecmp(orientation, "portrait") == 0) {
715 return_features.orientation("portrait");
717 else if (strcasecmp(orientation, "landscape") == 0) {
718 return_features.orientation("landscape");
720 } // end if orientation feature
725 CanvasRenderer::dobreak(PartialElementFeatures &return_features,
726 const FeatureSet &local,
727 const FeatureSet& /*complete*/, Symbol **symbols)
729 const char *breakvalue = *local.lookup (*symbols[LINEBREAK])->value();
732 cerr << "linebreak: " << breakvalue << endl;
734 if (strcasecmp (breakvalue, "before") == 0)
735 return_features.linebreak (LINEBREAK_BEFORE);
737 if (strcasecmp (breakvalue, "after") == 0)
738 return_features.linebreak (LINEBREAK_AFTER);
740 if (strcasecmp (breakvalue, "both") == 0)
741 return_features.linebreak (LINEBREAK_BOTH);
745 node *new_spnode = 0 ;
746 const char *breakvalue = *local.lookup(*symbols[BREAK])->value();
748 if (strcasecmp(breakvalue, "line") == 0)
750 // get interparagraph spacing
751 const Feature *spacefp = complete.deep_lookup(symbols[MARGIN],
754 int spacing = 10 ; // default value
757 spacing = point2pixel(*spacefp->value());
760 cerr << "break: spacing = " << spacing << endl ;
763 // insert a space between paragraphs
764 #ifdef TML_NO_THIS_ASSIGNMENT
765 model* to_model = current_node->get_model();
766 new_spnode = new(to_model) space_node(spacing, to_model);
768 new_spnode = new space_node(spacing, current_node->get_model());
770 new_spnode->vcc(current_node->vcc());
778 CanvasRenderer::dopage(PartialElementFeatures &return_features,
779 const FeatureSet &local,
780 const FeatureSet& /*complete*/, Symbol **symbols)
782 const char *breakvalue = *local.lookup (*symbols[PAGEBREAK])->value();
784 cerr << "pagebreak: " << breakvalue << endl;
786 if (strcasecmp (breakvalue, "before") == 0) {
787 return_features.pagebreak (PAGEBREAK_BEFORE);
790 if (strcasecmp (breakvalue, "after") == 0) {
791 return_features.pagebreak (PAGEBREAK_AFTER);
794 if (strcasecmp (breakvalue, "both") == 0) {
795 return_features.pagebreak(PAGEBREAK_BOTH);
802 CanvasRenderer::domargin(ElementFeatures &return_features,
803 const FeatureSet &complete,
806 const FeatureSet *marginset = *complete.lookup(symbols[MARGIN])->value();
816 //const Feature *f = marginset->lookup(symbols[FIRST]);
817 const Feature *l = marginset->lookup(symbols[LEFT]);
818 const Feature *r = marginset->lookup(symbols[RIGHT]);
819 const Feature *t = marginset->lookup(symbols[TOP]);
820 const Feature *b = marginset->lookup(symbols[BOTTOM]);
823 if (l) left = point2pixel(*l->value());
824 if (r) right = point2pixel(*r->value());
825 if (t) top = point2pixel(*t->value());
826 if (b) bottom = point2pixel(*b->value());
828 // external systems for print form
831 right_margin = right;
833 bottom_margin = bottom;
836 catch_noarg (StyleSheetException &)
839 cerr << "MarginFPtml: style sheet exception" << endl;
845 cout << "[ " << left << ", " << right << "] [ "
846 << top << ", " << bottom << "]" << endl;
850 return_features.margin().first (first);
851 return_features.margin().left (left);
852 return_features.margin().right (right);
853 return_features.margin().top (top);
854 return_features.margin().bottom (bottom);
858 #ifdef TML_NO_THIS_ASSIGNMENT
859 model* to_model = current_node->get_model();
860 prop_vec *pvec = new(to_model) prop_vec(to_model) ;
862 prop_vec *pvec = new prop_vec(current_node->get_model()) ;
865 pvec->attach(make_margin_prop(left, right, top, bottom,
866 current_node->get_model()));
868 current_node->prop_attach(pvec);
874 CanvasRenderer::doborder (ElementFeatures &return_features,
875 const FeatureSet &local,
878 const Feature *feature = local.lookup(symbols[BORDER]);
882 const FeatureValue *fv = feature->value();
884 assert (fv->type() == FeatureValue::featureset);
886 if (fv->type() == FeatureValue::featureset)
888 const FeatureSet *fs = ((FeatureValueFeatureSet*)fv)->value();
890 const Feature *display_feature = fs->lookup(symbols[DISPLAY]);
892 if (display_feature) {
893 const char *border = *display_feature->value();
895 // valid values are one of:
896 // All Bottom Horiz Left Right Top Vert
898 if (strcasecmp (border, "all") == 0)
899 return_features.border (_DtCvBORDER_FULL);
900 else if (strcasecmp (border, "bottom") == 0)
901 return_features.border (_DtCvBORDER_BOTTOM);
902 else if (strcasecmp (border, "horiz") == 0)
903 return_features.border (_DtCvBORDER_HORZ);
904 else if (strcasecmp (border, "left") == 0)
905 return_features.border (_DtCvBORDER_LEFT);
906 else if (strcasecmp (border, "right") == 0)
907 return_features.border (_DtCvBORDER_RIGHT);
908 else if (strcasecmp (border, "top") == 0)
909 return_features.border (_DtCvBORDER_TOP);
910 else if (strcasecmp (border, "vert") == 0)
911 return_features.border (_DtCvBORDER_VERT);
913 else { // default to _DtCvBORDER_FULL (hard-coded default)
914 return_features.border (_DtCvBORDER_FULL);
917 const Feature *width_feature = fs->lookup(symbols[THICKNESS]);
920 return_features.border_width(point2pixel(*width_feature->value()));
926 CanvasRenderer::doposition(PartialElementFeatures &return_features,
927 const FeatureSet &local,
931 const FeatureSet *pset = *local.lookup(symbols[POSITION])->value();
933 const Feature *horiz = pset->lookup(symbols[HORIZ]);
934 const Feature *vert = pset->lookup(symbols[VERT]);
938 const char *hvalue = *horiz->value();
939 if (strcasecmp (hvalue, "lcorner") == 0)
940 return_features.position().horiz(_DtCvJUSTIFY_LEFT_CORNER) ;
942 if (strcasecmp (hvalue, "left") == 0)
943 return_features.position().horiz(_DtCvJUSTIFY_LEFT) ;
945 if (strcasecmp (hvalue, "lmargin") == 0)
946 return_features.position().horiz(_DtCvJUSTIFY_LEFT_MARGIN) ;
948 if (strcasecmp (hvalue, "rcorner") == 0)
949 return_features.position().horiz(_DtCvJUSTIFY_RIGHT_CORNER) ;
951 if (strcasecmp (hvalue, "right") == 0)
952 return_features.position().horiz(_DtCvJUSTIFY_RIGHT) ;
954 if (strcasecmp (hvalue, "rmargin") == 0)
955 return_features.position().horiz(_DtCvJUSTIFY_RIGHT_MARGIN) ;
957 if (strcasecmp (hvalue, "center") == 0)
958 return_features.position().horiz(_DtCvJUSTIFY_CENTER) ;
963 const char *vvalue = *vert->value();
964 if (strcasecmp (vvalue, "top") == 0)
965 return_features.position().vert(_DtCvJUSTIFY_TOP) ;
967 if (strcasecmp (vvalue, "bottom") == 0)
968 return_features.position().vert(_DtCvJUSTIFY_BOTTOM) ;
970 if (strcasecmp (vvalue, "middle") == 0)
971 return_features.position().vert(_DtCvJUSTIFY_CENTER) ;
977 CanvasRenderer::dolayout(PartialElementFeatures &return_features,
978 const FeatureSet &local,
979 const FeatureSet &complete,
982 const FeatureSet *locallayoutset = *local.lookup (symbols[LAYOUT])->value();
983 const FeatureSet *layoutset = *complete.lookup (symbols[LAYOUT])->value();
985 Layout &layout = return_features.layout() ;
987 const Feature *feature ;
989 feature = locallayoutset->lookup (symbols[ASPACE]) ;
991 layout.aspace(point2pixel(*feature->value()));
993 feature = locallayoutset->lookup (symbols[BSPACE]) ;
995 layout.bspace(point2pixel(*feature->value()));
997 feature = layoutset->lookup (symbols[LEADING]) ;
999 layout.leading(point2pixel(*feature->value()));
1001 feature = locallayoutset->lookup (symbols[FINDENT]) ;
1002 if (feature != NULL)
1003 layout.findent(point2pixel(*feature->value()));
1005 feature = locallayoutset->lookup (symbols[LINDENT]) ;
1006 if (feature != NULL)
1007 layout.lindent(point2pixel(*feature->value()));
1009 feature = locallayoutset->lookup (symbols[RINDENT]) ;
1010 if (feature != NULL)
1011 layout.rindent(point2pixel(*feature->value()));
1015 feature = layoutset->lookup (symbols[FLOW]);
1018 const char *flow = *feature->value();
1021 if (strcasecmp (flow, "verbatim") == 0)
1022 layout.flow (_DtCvLITERAL);
1023 else if (strcasecmp (flow, "filled") == 0)
1024 layout.flow (_DtCvDYNAMIC);
1028 feature = layoutset->lookup (symbols[JUSTIFY]);
1031 const char *justify = *feature->value();
1034 if (strcasecmp (justify, "left") == 0)
1035 layout.justify (_DtCvJUSTIFY_LEFT);
1036 else if (strcasecmp (justify, "right") == 0)
1037 layout.justify (_DtCvJUSTIFY_RIGHT);
1038 else if (strcasecmp (justify, "center") == 0)
1039 layout.justify (_DtCvJUSTIFY_CENTER);
1043 feature = layoutset->lookup (symbols[WRAP]) ;
1046 const char *wrap = *feature->value();
1049 if (strcasecmp (wrap, "block") == 0)
1050 layout.wrap (_DtCvWRAP);
1051 else if (strcasecmp (wrap, "join") == 0)
1052 layout.wrap (_DtCvWRAP_JOIN);
1053 else if (strcasecmp (wrap, "none") == 0)
1054 layout.wrap(_DtCvWRAP_NONE);
1061 CanvasRenderer::dowrap(ElementFeatures &, const FeatureSet &, Symbol **)
1065 CanvasRenderer::dohighlight(ElementFeatures &return_features,
1066 const FeatureSet &complete,
1069 const FeatureSet *hiliteset = *complete.lookup(symbols[HIGHLIGHT])->value();
1071 cerr << "HIGHLIGHT feature";
1072 CC_TPtrSlistIterator<Feature> iter(*(FeatureSet*)hiliteset);
1074 for(; item = iter(); ) {
1075 cerr << ' ' << (const char*)item->name().name();
1077 cerr << " found" << endl;
1080 const Feature *underlineF = hiliteset->lookup(symbols[UNDERLINE]);
1083 underline = *underlineF->value();
1085 return_features.highlight().underline(True);
1087 return_features.highlight().underline(False);
1089 const Feature *strikethroughF = hiliteset->lookup(symbols[STRIKETHROUGH]);
1090 int strikethrough = 0;
1092 strikethrough = *strikethroughF->value();
1094 return_features.highlight().strikethrough(True);
1096 return_features.highlight().strikethrough(False);
1098 const Feature *overlineF = hiliteset->lookup(symbols[OVERLINE]);
1101 overline = *overlineF->value();
1103 return_features.highlight().overline(True);
1105 return_features.highlight().overline(False);
1107 const Feature *bgcolorF = hiliteset->lookup(symbols[BGCOLOR]);
1109 return_features.highlight().bg_color(*bgcolorF->value());
1111 const Feature *fgcolorF = hiliteset->lookup(symbols[FGCOLOR]);
1113 return_features.highlight().fg_color(*fgcolorF->value());
1117 CanvasRenderer::doprefix(ElementFeatures &return_features,
1118 const FeatureSet &local,
1119 const FeatureSet &complete,
1122 // NOTE: need to inform find_search_hits that vcc counting is to skip this
1123 // node...perhaps because vcc is 0 or maybe set a flag?
1125 #ifdef PREFIX_TESTING
1126 cerr << "doprefix(): " << endl;
1129 const Feature *prefix_text = local.deep_lookup(symbols[PREFIX],
1130 symbols[CONTENT],0);
1133 const char *text = *prefix_text->value();
1137 PartialElementFeatures &features = return_features.prefix();
1139 features.text (text);
1141 const Feature *prefixF = local.lookup(*symbols[PREFIX]);
1142 const FeatureSet *prefix_set = ((FeatureValueFeatureSet*)prefixF->value())->value () ;
1143 FeatureSet *merged = new FeatureSet(complete, *prefix_set);
1146 cerr << "Prefix Set: " << *prefix_set << endl;
1149 CC_TPtrSlistIterator<Feature> next(*(FeatureSet*)prefix_set);
1152 // for each feature, look up the id in the local symbol table, and use
1153 // that id as an index into a the table of processing objects which
1154 // handle each feature
1156 // get id and do lookup
1158 const Symbol &feature = next.key()->name();
1160 #ifdef FEATURE_DEBUG
1161 cerr << "\tfeature = " << feature.name() << endl;
1164 if (feature == *symbols[LINEBREAK])
1165 dobreak(features, *prefix_set, complete, symbols);
1167 if (feature == *symbols[FONT])
1168 dofont(features, *merged, symbols);
1169 else if (feature == *symbols[POSITION])
1170 doposition (features, *prefix_set, symbols);
1171 else if (feature == *symbols[LAYOUT])
1172 dolayout (features, *prefix_set, *merged, symbols);
1180 CanvasRenderer::dosuffix(ElementFeatures &return_features,
1181 const FeatureSet &local,
1182 const FeatureSet &complete,
1186 const Feature *suffix_text = local.deep_lookup(symbols[SUFFIX],
1187 symbols[CONTENT],0);
1190 const char *text = *suffix_text->value();
1194 PartialElementFeatures &features = return_features.suffix();
1196 const Feature *suffixF = local.lookup(*symbols[SUFFIX]);
1197 const FeatureSet *suffix_set = ((FeatureValueFeatureSet*)suffixF->value())->value () ;
1198 FeatureSet *merged = new FeatureSet(complete, *suffix_set);
1200 CC_TPtrSlistIterator<Feature> next(*(FeatureSet*)suffix_set);
1203 // for each feature, look up the id in the local symbol table, and use
1204 // that id as an index into a the table of processing objects which
1205 // handle each feature
1207 // get id and do lookup
1209 const Symbol &feature = next.key()->name();
1211 #ifdef FEATURE_DEBUG
1212 cerr << "\tfeature = " << feature.name() << endl;
1215 if (feature == *symbols[LINEBREAK])
1216 dobreak(features, *suffix_set, complete, symbols);
1218 if (feature == *symbols[FONT])
1219 dofont(features, *merged, symbols);
1220 else if (feature == *symbols[POSITION])
1221 doposition (features, *suffix_set, symbols);
1222 else if (feature == *symbols[LAYOUT])
1223 dolayout (features, *suffix_set, *merged, symbols);
1227 features.text (text);
1231 // NOTE: need to inform find_search_hits that vcc counting is to skip this
1232 // node...perhaps because vcc is 0 or maybe set a flag?
1234 // NOTE: need to handle other suffix things too
1235 // (space, font, wrap, tab, margins, highlight, underline, color)
1237 node *suffix_node = 0 ;
1238 gnode *new_gnode = 0;
1239 const Feature *suffix_text = local.deep_lookup(symbols[SUFFIX],
1240 symbols[CONTENT],0);
1243 const char *text = *suffix_text->value();
1244 #ifdef TML_NO_THIS_ASSIGNMENT
1245 model* to_model = current_node->get_model();
1246 new_gnode = new(to_model) gnode(to_model);
1248 new_gnode = new gnode(current_node->get_model());
1251 int size = strlen(text);
1252 TML_CHAR_TYPE* buffer = new TML_CHAR_TYPE[ size + 1 ];
1253 int nc = mbstowcs(buffer, text, size + 1);
1255 new_gnode->attach_data(buffer, nc);
1258 new_gnode->attach_data((void*)text, strlen(text));
1261 // process suffix features recursively
1262 const Feature *suffixF = local.lookup(*symbols[SUFFIX]);
1264 const FeatureSet *suffix_set = ((FeatureValueFeatureSet*)suffixF->value())->value();
1266 #ifdef TML_NO_THIS_ASSIGNMENT
1267 to_model = current_node->get_model();
1268 suffix_node = new(to_model) bnode(to_model) ;
1270 suffix_node = new bnode(current_node->get_model()) ;
1273 // set vcc to ULONG_MAX. When looking for search hits, if we are down
1274 // this branch then the main trunk (actual data) contains the vcc we are
1275 // looking for. This large vcc prevents the search from continuing to
1276 // the right into any prefix nodes.
1278 suffix_node->vcc(ULONG_MAX);
1280 node_dir dir = n_down ;
1281 node *root = suffix_node;
1283 // NOTE: ordering of merge parameters counts
1284 FeatureSet *merged = new FeatureSet(complete, *suffix_set);
1285 do_features(root, dir, *suffix_set, *merged, symbols); // recursive call
1288 root->connect_node(new_gnode, dir);
1290 return suffix_node ;
1295 CanvasRenderer::docolor(ElementFeatures &, const FeatureSet &, Symbol **)
1299 CanvasRenderer::do_unsupported_feature(const Symbol &feature_name)
1301 // NOTE: maybe give warning in Author mode
1303 cerr << "Unsupported feature: " << feature_name << endl;
1308 CanvasRenderer::do_features(ElementFeatures &return_features,
1309 const FeatureSet &local,
1310 const FeatureSet &complete,
1313 // NOTE: notice args passed by reference
1314 // this routine modifies the calling arguments current_node and connect_dir
1315 // in the calling routine if breaks, prefix or suffix occur in the feature
1318 node *break_node = 0;
1319 node *prefix_node = 0;
1320 node *suffix_node = 0;
1323 CC_TPtrSlistIterator<Feature> next(*(FeatureSet*)&local);
1326 // for each feature, look up the id in the local symbol table, and use
1327 // that id as an index into a the table of processing objects which
1328 // handle each feature
1330 // get id and do lookup
1333 // check for ignore symbol
1334 // NOTE: special hack - jbm - needs to be fixed to do proper vcc counting
1335 if (next.key()->name() == *f_symbols[IGNORE])
1337 connect_dir = n_right ;
1341 const Symbol &feature = next.key()->name();
1343 #ifdef FEATURE_DEBUG
1344 cerr << "feature = " << feature.name() << endl;
1347 if (feature == *symbols[LINEBREAK])
1348 dobreak(return_features, local, complete, symbols);
1349 else if (feature == *symbols[FONT])
1350 dofont(return_features, complete, symbols);
1351 else if (feature == *symbols[MARGIN])
1352 domargin(return_features, complete, symbols);
1353 else if (feature == *symbols[POSITION])
1354 doposition (return_features, local, symbols);
1355 else if (feature == *symbols[LAYOUT])
1356 dolayout (return_features, local, complete, symbols);
1357 else if (feature == *symbols[BORDER])
1358 doborder (return_features, local, symbols);
1359 else if (feature == *symbols[TABLE])
1360 dotable (return_features, local, symbols);
1361 else if (feature == *symbols[TGROUP])
1362 dotgroup (return_features, local, symbols);
1363 else if (feature == *symbols[COLFORMAT])
1364 docolformat (return_features, local, symbols);
1365 else if (feature == *symbols[CELL])
1366 docell (return_features, local, symbols);
1367 else if (feature == *symbols[ROW])
1368 dorow (return_features, local, symbols);
1369 else if (feature == *symbols[PREFIX])
1370 doprefix(return_features, local, complete, symbols);
1371 else if (feature == *symbols[SUFFIX])
1372 dosuffix(return_features, local, complete, symbols);
1375 else if (feature == *symbols[UNDERLINE])
1376 dounderline(return_features, current_node, local, symbols);
1378 else if (feature == *symbols[WRAP])
1379 dowrap(return_features, current_node, local, symbols);
1382 else if (feature == *symbols[COLOR])
1383 docolor(return_features, current_node, local, symbols);
1388 // if printing in progress, check for print features
1389 if (window_system().printing()) {
1392 if (feature == *symbols[MEDIA]) {
1393 domedia(return_features, complete, symbols);
1397 else if (feature == *symbols[PAGEBREAK]) {
1398 dopage(return_features, local, complete, symbols);
1400 // otherwise features are unsupported
1402 do_unsupported_feature(feature);
1408 CC_TPtrSlistIterator<Feature> iter(*(FeatureSet*)&complete);
1410 const Symbol &feature = iter.key()->name();
1411 if (feature == *symbols[HIGHLIGHT])
1412 dohighlight(return_features, complete, symbols);
1413 else if (feature == *symbols[IGNORE]) {
1414 Feature *ignore = iter.key();
1416 fprintf(stderr, "IGNORE value=%d\n", (int)*(ignore->value()));
1418 return_features.ignore((int)*(ignore->value()));
1425 current_node->connect_node(prefix_node, connect_dir);
1426 current_node = prefix_node ;
1427 connect_dir = n_right ;
1431 current_node->connect_node(break_node, connect_dir);
1432 current_node = break_node ;
1433 connect_dir = n_right ;
1437 current_node->connect_node(suffix_node, connect_dir);
1438 current_node = suffix_node ;
1439 connect_dir = n_left ;
1446 CanvasRenderer::dotable (ElementFeatures &return_features,
1447 const FeatureSet &local,
1451 cerr << "dotable" << endl;
1454 const FeatureSet *tset = *local.lookup (symbols[TABLE])->value();
1456 const Feature* frame_feature = tset->lookup(symbols[FRAME]);
1461 table = new TableDefn((const char*)(*frame_feature->value()));
1463 table = new TableDefn((TableDefn::table_frame_t)
1464 TableDefn::table_frame_default);
1466 const Feature *colsep_feature = tset->lookup(symbols[COLSEP]);
1467 if (colsep_feature) {
1468 int colsep = point2pixel(*colsep_feature->value());
1469 table->colsep(colsep);
1471 cerr << "COLSEP specified in table, number=" << colsep << endl;
1475 const Feature *rowsep_feature = tset->lookup(symbols[ROWSEP]);
1476 if (rowsep_feature) {
1477 int rowsep = point2pixel(*rowsep_feature->value());
1478 table->rowsep(rowsep);
1480 cerr << "ROWSEP specified in table, number=" << rowsep << endl;
1484 return_features.table(table);
1488 CanvasRenderer::dotgroup (ElementFeatures &return_features,
1489 const FeatureSet &local,
1493 cerr << "dotgroup" << endl;
1496 const FeatureSet *tset = *local.lookup (symbols[TGROUP])->value();
1498 const Feature* justify_feature = tset->lookup(symbols[JUSTIFY]);
1500 _DtCvFrmtOption justify = _DtCvOPTION_BAD;
1502 if (justify_feature) {
1503 const char *str = *justify_feature->value();
1506 if (strcasecmp(str, "left") == 0)
1507 justify = _DtCvJUSTIFY_LEFT;
1508 else if (strcasecmp(str, "right") == 0)
1509 justify = _DtCvJUSTIFY_RIGHT;
1510 else if (strcasecmp(str, "center") == 0)
1511 justify = _DtCvJUSTIFY_CENTER;
1515 const Feature* vjustify_feature = tset->lookup(symbols[VJUSTIFY]);
1517 _DtCvFrmtOption vjustify = _DtCvOPTION_BAD;
1519 if (vjustify_feature) {
1520 const char *str = *vjustify_feature->value();
1523 if (strcasecmp(str, "top") == 0)
1524 vjustify = _DtCvJUSTIFY_TOP;
1525 else if (strcasecmp(str, "bottom") == 0)
1526 vjustify = _DtCvJUSTIFY_BOTTOM;
1527 else if (strcasecmp(str, "middle") == 0)
1528 vjustify = _DtCvJUSTIFY_CENTER;
1532 TGDefn *tgroup = new TGDefn(justify, vjustify);
1534 const Feature *colsepF = tset->lookup(symbols[COLSEP]);
1536 int colsep = point2pixel(*colsepF->value());
1537 tgroup->colsep(colsep);
1539 cerr << "COLSEP specified in tgroup, number=" << colsep << endl;
1543 const Feature *rowsepF = tset->lookup(symbols[ROWSEP]);
1545 int rowsep = point2pixel(*rowsepF->value());
1546 tgroup->rowsep(rowsep);
1548 cerr << "ROWSEP specified in tgroup, number=" << rowsep << endl;
1552 return_features.tgroup(tgroup);
1554 const Feature *char_alignF = tset->lookup(symbols[CHARALIGN]);
1556 tgroup->char_align(*char_alignF->value());
1560 CanvasRenderer::docolformat(ElementFeatures &return_features,
1561 const FeatureSet &local,
1565 cerr << "docolformat" << endl;
1567 // have to iterate over colformat attributes
1569 const Feature *feature = local.lookup(symbols[COLFORMAT]);
1570 const FeatureValue *fv = feature->value();
1572 const FeatureSet *set = ((FeatureValueFeatureSet*)fv)->value();
1573 ColFormat *colf = new ColFormat ;
1578 const Feature *widthF = set->lookup (symbols[WIDTH]) ;
1580 colf->width(point2pixel(*widthF->value()));
1582 const Feature *nameF = set->lookup (symbols[NAME]) ;
1584 colf->name (*nameF->value());
1586 const Feature *justifyF = set->lookup(symbols[JUSTIFY]);
1589 _DtCvFrmtOption justify = _DtCvOPTION_BAD ;
1590 const char *justify_name = *justifyF->value();
1592 if (!strcasecmp (justify_name, "left"))
1594 justify = _DtCvJUSTIFY_LEFT;
1597 if (!strcasecmp (justify_name, "right"))
1599 justify = _DtCvJUSTIFY_RIGHT ;
1602 if (!strcasecmp (justify_name, "center"))
1604 justify = _DtCvJUSTIFY_CENTER ;
1607 if (!strcasecmp (justify_name, "char"))
1609 justify = _DtCvJUSTIFY_CHAR ;
1611 // CharAlign is effective only for _DtCvJUSTIFY_CHAR
1612 const Feature *char_alignF = set->lookup (symbols[CHARALIGN]);
1614 colf->char_align (*char_alignF->value()) ;
1616 colf->justify (justify);
1625 const Feature *colsepF = set->lookup(symbols[COLSEP]);
1627 int colsep = point2pixel(*colsepF->value());
1628 colf->colsep(colsep);
1630 cerr << "COLSEP specified in colformat, number=" << colsep << endl;
1634 const Feature *rowsepF = set->lookup(symbols[ROWSEP]);
1636 int rowsep = point2pixel(*rowsepF->value());
1637 colf->rowsep(rowsep);
1639 cerr << "ROWSEP specified in colformat, number=" << rowsep << endl;
1643 return_features.col_format (colf); // remember to add into table
1646 CanvasRenderer::docell (ElementFeatures &return_features,
1647 const FeatureSet &local,
1650 #ifdef TABLE_DEBUG_X
1651 static int cell_count = 0 ;
1652 cerr << "docell: " << cell_count << endl;
1655 const FeatureSet *cset = *local.lookup (symbols[CELL])->value() ;
1657 const Feature *mr = cset->lookup (symbols[MOREROWS]);
1660 return_features.cell().spanrows (int(point2pixel(*mr->value())) + 1);
1662 const Feature *cref = cset->lookup (symbols[COLREF]);
1664 return_features.cell().colref (strdup (*cref->value()));
1666 const Feature *vjustify_feature = cset->lookup(symbols[VJUSTIFY]);
1667 if (vjustify_feature) {
1668 const char *vjustify = *vjustify_feature->value();
1670 if (vjustify && *vjustify) {
1671 #ifdef VJUSTIFY_DEBUG
1672 cerr << "cell vjustify = " << vjustify << endl;
1674 if (strcasecmp(vjustify, "top") == 0)
1675 return_features.cell().vjustify(_DtCvJUSTIFY_TOP);
1676 else if (strcasecmp(vjustify, "middle") == 0)
1677 return_features.cell().vjustify(_DtCvJUSTIFY_CENTER);
1678 else if (strcasecmp(vjustify, "bottom") == 0)
1679 return_features.cell().vjustify(_DtCvJUSTIFY_BOTTOM);
1681 return_features.cell().vjustify(_DtCvOPTION_BAD);
1685 const Feature *justify_feature = cset->lookup(symbols[JUSTIFY]);
1686 if (justify_feature) {
1687 const char *justify = *justify_feature->value();
1689 if (strcasecmp(justify, "left") == 0)
1690 return_features.cell().justify(_DtCvJUSTIFY_LEFT);
1691 else if (strcasecmp(justify, "right") == 0)
1692 return_features.cell().justify(_DtCvJUSTIFY_RIGHT);
1693 else if (strcasecmp(justify, "center") == 0)
1694 return_features.cell().justify(_DtCvJUSTIFY_CENTER);
1695 else if (strcasecmp(justify, "char") == 0) {
1696 return_features.cell().justify(_DtCvJUSTIFY_CHAR);
1698 // CharAlign is effective only for _DtCvJUSTIFY_CHAR
1699 const Feature *char_alignF = cset->lookup (symbols[CHARALIGN]);
1701 return_features.cell().char_align(*char_alignF->value());
1705 return_features.cell().justify(_DtCvOPTION_BAD);
1708 const Feature *colsepF = cset->lookup(symbols[COLSEP]);
1710 int colsep = point2pixel(*colsepF->value());
1711 return_features.cell().colsep(colsep);
1713 cerr << "COLSEP specified in cell, number=" << colsep << endl;
1717 const Feature *rowsepF = cset->lookup(symbols[ROWSEP]);
1719 int rowsep = point2pixel(*rowsepF->value());
1720 return_features.cell().rowsep(rowsep);
1722 cerr << "ROWSEP specified in cell, number=" << rowsep << endl;
1726 return_features.cell().has_cell(True);
1729 CanvasRenderer::dorow (ElementFeatures &return_features,
1730 const FeatureSet &local,
1734 cerr << "dorow" << endl;
1737 RowDefn* rowdefn = new RowDefn;
1739 const FeatureSet* features;
1743 features = *local.lookup(symbols[ROW])->value();
1753 const Feature *vjustify_feature = features->lookup(symbols[VJUSTIFY]);
1755 if (vjustify_feature) {
1756 const char *vjustify = *vjustify_feature->value();
1758 if (vjustify && *vjustify) {
1759 #ifdef VJUSTIFY_DEBUG
1760 cerr << "vjustify = " << vjustify << endl;
1762 if (strcasecmp(vjustify, "top") == 0)
1763 rowdefn->vjustify(_DtCvJUSTIFY_TOP);
1764 else if (strcasecmp(vjustify, "middle") == 0)
1765 rowdefn->vjustify(_DtCvJUSTIFY_CENTER);
1766 else if (strcasecmp(vjustify, "bottom") == 0)
1767 rowdefn->vjustify(_DtCvJUSTIFY_BOTTOM);
1769 rowdefn->vjustify(_DtCvOPTION_BAD);
1773 const Feature *rowsepF = features->lookup(symbols[ROWSEP]);
1775 int rowsep = point2pixel(*rowsepF->value());
1776 rowdefn->rowsep(rowsep);
1778 cerr << "ROWSEP specified in row, number=" << rowsep << endl;
1783 return_features.row (rowdefn) ;