X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=ioncore%2Fgr.c;h=835c7ca2ad5b87f34ee32080a68a02df7f33d26a;hb=ae4260bb64817c11f9a7140324cd3e3ba113e297;hp=d4f5a151959e6c7242284647a50e8bc2b1da9f7c;hpb=8366314611bf30a0f31d25bf5f5023186fa87692;p=ion3.git diff --git a/ioncore/gr.c b/ioncore/gr.c index d4f5a15..835c7ca 100644 --- a/ioncore/gr.c +++ b/ioncore/gr.c @@ -1,17 +1,15 @@ /* * ion/ioncore/gr.c * - * Copyright (c) Tuomo Valkonen 1999-2006. + * Copyright (c) Tuomo Valkonen 1999-2007. * - * Ion is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. + * See the included file LICENSE for details. */ #include #include +#include #include #include #include "common.h" @@ -97,7 +95,7 @@ static bool gr_do_select_engine(const char *engine) /*EXTL_DOC - * Future requests for ''brushes'' are to be forwarded to the drawing engine + * Future requests for ``brushes'' are to be forwarded to the drawing engine * \var{engine}. If no engine of such name is known, a module with that name * is attempted to be loaded. This function is only intended to be called from * colour scheme etc. configuration files and can not be used to change the @@ -147,68 +145,303 @@ GrBrush *gr_get_brush(Window win, WRootWin *rootwin, const char *style) /*{{{ Scoring */ -uint gr_stylespec_score2(const char *spec, const char *attrib, - const char *attrib_p2) +static GrAttr star_id=STRINGID_NONE; + + +static int cmp(const void *a_, const void *b_) { - uint score=0; - uint a=0; - uint mult=1; + StringId a=*(const StringId*)a_; + StringId b=((const GrAttrScore*)b_)->attr; + + return (a < b ? -1 : ((a == b) ? 0 : 1)); +} - if(attrib==NULL){ - if(spec==NULL || strcmp(spec, "*")==0) - return 1; + +static uint scorefind(const GrStyleSpec *attr, const GrAttrScore *spec) +{ + GrAttrScore *res; + + if(attr->attrs==NULL) return 0; + + if(star_id==STRINGID_NONE) + star_id=stringstore_alloc("*"); + + if(spec->attr==star_id){ + /* Since every item occurs only once on the list, with a score, + * return the score of the star in the spec, instead of one. + */ + return spec->score; + } + + res=bsearch(&spec->attr, attr->attrs, attr->n, sizeof(GrAttrScore), cmp); + + return (res==NULL ? 0 : 2*res->score); +} + + +uint gr_stylespec_score2(const GrStyleSpec *spec, const GrStyleSpec *attr1, + const GrStyleSpec *attr2) +{ + uint score=0; + uint i; + + for(i=0; in; i++){ + int sc=scorefind(attr1, &spec->attrs[i]); + + if(attr2!=NULL) + sc=maxof(sc, scorefind(attr2, &spec->attrs[i])); + + if(sc==0){ + score=0; + break; + } + + score+=sc; } - while(1){ - if(*spec=='*'){ - score=score+mult; - spec++; - attrib=strchr(attrib, '-'); + return score; +} + + +uint gr_stylespec_score(const GrStyleSpec *spec, const GrStyleSpec *attr) +{ + return gr_stylespec_score2(spec, attr, NULL); +} + + +static uint count_dashes(const char *str) +{ + uint n=0; + + if(str!=NULL){ + while(1){ + const char *p=strchr(str, '-'); + if(p==NULL) + break; + n++; + str=p+1; + } + } + + return n; +} + + +bool gr_stylespec_load_(GrStyleSpec *spec, const char *str, bool no_order_score) +{ + uint score=(no_order_score ? 1 : count_dashes(str)+1); + + gr_stylespec_init(spec); + + while(str!=NULL){ + GrAttr a; + const char *p=strchr(str, '-'); + + if(p==NULL){ + a=stringstore_alloc(str); + str=p; }else{ - while(1){ - if(*attrib=='\0'){ - attrib=NULL; - break; - } - if(*attrib=='-') - break; - if(*spec!=*attrib) - return 0; - attrib++; - spec++; - } - score=score+2*mult; + a=stringstore_alloc_n(str, p-str); + str=p+1; } - if(*spec=='\0') - return score; - else if(*spec!='-') - return 0; + if(a==STRINGID_NONE) + goto fail; + + if(!gr_stylespec_add(spec, a, score)) + goto fail; + + stringstore_free(a); - if(attrib==NULL){ - if(a==0 && attrib_p2!=NULL){ - attrib=attrib_p2; - a++; - }else{ - return 0; - } - }else{ - attrib++; + if(!no_order_score) + score--; + } + + return TRUE; + +fail: + gr_stylespec_unalloc(spec); + + return FALSE; +} + + +bool gr_stylespec_load(GrStyleSpec *spec, const char *str) +{ + return gr_stylespec_load_(spec, str, FALSE); +} + + +void gr_stylespec_unalloc(GrStyleSpec *spec) +{ + uint i; + + for(i=0; in; i++) + stringstore_free(spec->attrs[i].attr); + + if(spec->attrs!=NULL){ + free(spec->attrs); + spec->attrs=NULL; + } + + spec->n=0; +} + + +void gr_stylespec_init(GrStyleSpec *spec) +{ + spec->attrs=NULL; + spec->n=0; +} + + +static bool gr_stylespec_find_(const GrStyleSpec *spec, GrAttr a, int *idx_ge) +{ + bool found=FALSE; + uint i; + + for(i=0; in; i++){ + if(spec->attrs[i].attr>=a){ + found=(spec->attrs[i].attr==a); + break; } + } + + *idx_ge=i; + return found; +} - spec++; - mult=mult*3; + +bool gr_stylespec_isset(const GrStyleSpec *spec, GrAttr a) +{ + int idx_ge; + + return gr_stylespec_find_(spec, a, &idx_ge); +} + + +bool gr_stylespec_add(GrStyleSpec *spec, GrAttr a, uint score) +{ + static const uint sz=sizeof(GrAttrScore); + GrAttrScore *idsn; + int idx_ge; + + if(a==GRATTR_NONE || score==0) + return TRUE; + + if(gr_stylespec_find_(spec, a, &idx_ge)){ + spec->attrs[idx_ge].score+=score; + return TRUE; } + + idsn=(GrAttrScore*)realloc(spec->attrs, (spec->n+1)*sz); + + if(idsn==NULL) + return FALSE; + + stringstore_ref(a); + + memmove(idsn+idx_ge+1, idsn+idx_ge, (spec->n-idx_ge)*sz); + + idsn[idx_ge].attr=a; + idsn[idx_ge].score=score; + spec->attrs=idsn; + spec->n++; + + return TRUE; } -uint gr_stylespec_score(const char *spec, const char *attrib) +bool gr_stylespec_set(GrStyleSpec *spec, GrAttr a) { - return gr_stylespec_score2(spec, attrib, NULL); + return gr_stylespec_add(spec, a, 1); } +void gr_stylespec_unset(GrStyleSpec *spec, GrAttr a) +{ + static const uint sz=sizeof(GrAttrScore); + GrAttrScore *idsn; + int idx_ge; + + if(a==GRATTR_NONE) + return; + + if(!gr_stylespec_find_(spec, a, &idx_ge)) + return; + + stringstore_free(spec->attrs[idx_ge].attr); + + memmove(spec->attrs+idx_ge, spec->attrs+idx_ge+1, + (spec->n-idx_ge-1)*sz); + + spec->n--; + + idsn=(GrAttrScore*)realloc(spec->attrs, (spec->n)*sz); + + if(idsn!=NULL || spec->n==0) + spec->attrs=idsn; +} + + +static bool gr_stylespec_do_init_from(GrStyleSpec *dst, const GrStyleSpec *src) +{ + uint i; + + if(src->n==0) + return TRUE; + + dst->attrs=ALLOC_N(GrAttrScore, src->n); + + if(dst->attrs==NULL) + return FALSE; + + for(i=0; in; i++){ + dst->attrs[i]=src->attrs[i]; + stringstore_ref(dst->attrs[i].attr); + } + + dst->n=src->n; + + return TRUE; +} + + +bool gr_stylespec_append(GrStyleSpec *dst, const GrStyleSpec *src) +{ + uint i; + bool ok=TRUE; + + if(dst->attrs==NULL){ + ok=gr_stylespec_do_init_from(dst, src); + }else{ + for(i=0; in; i++){ + if(!gr_stylespec_add(dst, src->attrs[i].attr, src->attrs[i].score)) + ok=FALSE; + } + } + + return ok; +} + + +bool gr_stylespec_equals(const GrStyleSpec *s1, const GrStyleSpec *s2) +{ + uint i; + + if(s1->n!=s2->n) + return FALSE; + + for(i=0; in; i++){ + if(s1->attrs[i].attr!=s2->attrs[i].attr) + return FALSE; + } + + return TRUE; +} + + /*}}}*/ @@ -294,17 +527,16 @@ DYNFUN bool grbrush_get_extra(GrBrush *brush, const char *key, /*{{{ Dynfuns/Borders */ -void grbrush_draw_border(GrBrush *brush, const WRectangle *geom, - const char *attrib) +void grbrush_draw_border(GrBrush *brush, const WRectangle *geom) { - CALL_DYN(grbrush_draw_border, brush, (brush, geom, attrib)); + CALL_DYN(grbrush_draw_border, brush, (brush, geom)); } void grbrush_draw_borderline(GrBrush *brush, const WRectangle *geom, - const char *attrib, GrBorderLine line) + GrBorderLine line) { - CALL_DYN(grbrush_draw_borderline, brush, (brush, geom, attrib, line)); + CALL_DYN(grbrush_draw_borderline, brush, (brush, geom, line)); } @@ -315,11 +547,9 @@ void grbrush_draw_borderline(GrBrush *brush, const WRectangle *geom, void grbrush_draw_string(GrBrush *brush, int x, int y, - const char *str, int len, bool needfill, - const char *attrib) + const char *str, int len, bool needfill) { - CALL_DYN(grbrush_draw_string, brush, - (brush, x, y, str, len, needfill, attrib)); + CALL_DYN(grbrush_draw_string, brush, (brush, x, y, str, len, needfill)); } @@ -339,19 +569,16 @@ uint grbrush_get_text_width(GrBrush *brush, const char *text, uint len) void grbrush_draw_textbox(GrBrush *brush, const WRectangle *geom, - const char *text, const char *attr, - bool needfill) + const char *text, bool needfill) { - CALL_DYN(grbrush_draw_textbox, brush, - (brush, geom, text, attr, needfill)); + CALL_DYN(grbrush_draw_textbox, brush, (brush, geom, text, needfill)); } void grbrush_draw_textboxes(GrBrush *brush, const WRectangle *geom, int n, const GrTextElem *elem, - bool needfill, const char *common_attrib) + bool needfill) { - CALL_DYN(grbrush_draw_textboxes, brush, - (brush, geom, n, elem, needfill, common_attrib)); + CALL_DYN(grbrush_draw_textboxes, brush, (brush, geom, n, elem, needfill)); } @@ -374,10 +601,9 @@ void grbrush_enable_transparency(GrBrush *brush, GrTransparency tr) } -void grbrush_fill_area(GrBrush *brush, const WRectangle *geom, - const char *attr) +void grbrush_fill_area(GrBrush *brush, const WRectangle *geom) { - CALL_DYN(grbrush_fill_area, brush, (brush, geom, attr)); + CALL_DYN(grbrush_fill_area, brush, (brush, geom)); } @@ -387,6 +613,24 @@ void grbrush_clear_area(GrBrush *brush, const WRectangle *geom) } +void grbrush_init_attr(GrBrush *brush, const GrStyleSpec *spec) +{ + CALL_DYN(grbrush_init_attr, brush, (brush, spec)); +} + + +void grbrush_set_attr(GrBrush *brush, GrAttr attr) +{ + CALL_DYN(grbrush_set_attr, brush, (brush, attr)); +} + + +void grbrush_unset_attr(GrBrush *brush, GrAttr attr) +{ + CALL_DYN(grbrush_unset_attr, brush, (brush, attr)); +} + + /*}}}*/ @@ -394,7 +638,7 @@ void grbrush_clear_area(GrBrush *brush, const WRectangle *geom) /*EXTL_DOC - * Read drawing engine configuration file \file{draw.lua}. + * Read drawing engine configuration file \file{look.lua}. */ EXTL_EXPORT_AS(gr, read_config) void gr_read_config()