X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=de%2Fdraw.c;h=c48d49ab508dea40e56753aa74d07605ffa3297a;hb=ae4260bb64817c11f9a7140324cd3e3ba113e297;hp=aae2dae629d30bb0109aaf67fead4c58b5dc7f64;hpb=8366314611bf30a0f31d25bf5f5023186fa87692;p=ion3.git diff --git a/de/draw.c b/de/draw.c index aae2dae..c48d49a 100644 --- a/de/draw.c +++ b/de/draw.c @@ -1,12 +1,9 @@ /* * ion/de/draw.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 @@ -15,6 +12,7 @@ #include #include #include +#include #include "brush.h" #include "font.h" #include "private.h" @@ -26,16 +24,16 @@ static DEColourGroup *destyle_get_colour_group2(DEStyle *style, - const char *attr_p1, - const char *attr_p2) + const GrStyleSpec *a1, + const GrStyleSpec *a2) { int i, score, maxscore=0; DEColourGroup *maxg=&(style->cgrp); while(style!=NULL){ for(i=0; in_extra_cgrps; i++){ - score=gr_stylespec_score2(style->extra_cgrps[i].spec, - attr_p1, attr_p2); + score=gr_stylespec_score2(&style->extra_cgrps[i].spec, a1, a2); + if(score>maxscore){ maxg=&(style->extra_cgrps[i]); maxscore=score; @@ -49,19 +47,25 @@ static DEColourGroup *destyle_get_colour_group2(DEStyle *style, DEColourGroup *debrush_get_colour_group2(DEBrush *brush, - const char *attr_p1, - const char *attr_p2) + const GrStyleSpec *a1, + const GrStyleSpec *a2) { - return destyle_get_colour_group2(brush->d, attr_p1, attr_p2); + return destyle_get_colour_group2(brush->d, a1, a2); } -DEColourGroup *debrush_get_colour_group(DEBrush *brush, const char *attr) +DEColourGroup *debrush_get_colour_group(DEBrush *brush, const GrStyleSpec *attr) { return destyle_get_colour_group2(brush->d, attr, NULL); } +DEColourGroup *debrush_get_current_colour_group(DEBrush *brush) +{ + return debrush_get_colour_group(brush, debrush_get_current_attr(brush)); +} + + /*}}}*/ @@ -106,8 +110,8 @@ static void do_draw_border(Window win, GC gc, int x, int y, int w, int h, b=0; for(i=0; id->border); - GC gc=brush->d->normal_gc; - Window win=brush->win; - - switch(bd->style){ - case DEBORDER_RIDGE: - draw_border(win, gc, &geom, bd->hl, bd->sh, cg->hl, cg->sh); - case DEBORDER_INLAID: - draw_border(win, gc, &geom, bd->pad, bd->pad, cg->pad, cg->pad); - draw_border(win, gc, &geom, bd->sh, bd->hl, cg->sh, cg->hl); - break; - case DEBORDER_GROOVE: - draw_border(win, gc, &geom, bd->sh, bd->hl, cg->sh, cg->hl); - draw_border(win, gc, &geom, bd->pad, bd->pad, cg->pad, cg->pad); - draw_border(win, gc, &geom, bd->hl, bd->sh, cg->hl, cg->sh); - break; - case DEBORDER_ELEVATED: - default: - draw_border(win, gc, &geom, bd->hl, bd->sh, cg->hl, cg->sh); - draw_border(win, gc, &geom, bd->pad, bd->pad, cg->pad, cg->pad); - break; - } -} - - -void debrush_draw_border(DEBrush *brush, - const WRectangle *geom, - const char *attrib) -{ - DEColourGroup *cg=debrush_get_colour_group(brush, attrib); - if(cg!=NULL) - debrush_do_draw_border(brush, *geom, cg); -} - - static void draw_borderline(Window win, GC gc, WRectangle *geom, uint tl, uint br, DEColour tlc, DEColour brc, GrBorderLine line) { - if(line==GR_BORDERLINE_LEFT && geom->h>0){ + if(line==GR_BORDERLINE_LEFT && geom->h>0 && tl>0){ XSetForeground(ioncore_g.dpy, gc, tlc); - XDrawRectangle(ioncore_g.dpy, win, gc, geom->x, geom->y, tl, geom->h); + XSetBackground(ioncore_g.dpy, gc, tlc); + XFillRectangle(ioncore_g.dpy, win, gc, geom->x, geom->y, tl, geom->h); geom->x+=tl; - }else if(line==GR_BORDERLINE_TOP && geom->w>0){ + }else if(line==GR_BORDERLINE_TOP && geom->w>0 && tl>0){ XSetForeground(ioncore_g.dpy, gc, tlc); - XDrawRectangle(ioncore_g.dpy, win, gc, geom->x, geom->y, geom->w, tl); + XSetBackground(ioncore_g.dpy, gc, tlc); + XFillRectangle(ioncore_g.dpy, win, gc, geom->x, geom->y, geom->w, tl); geom->y+=tl; - }else if(line==GR_BORDERLINE_RIGHT && geom->h>0){ + }else if(line==GR_BORDERLINE_RIGHT && geom->h>0 && br>0){ XSetForeground(ioncore_g.dpy, gc, brc); - XDrawRectangle(ioncore_g.dpy, win, gc, geom->x+geom->w-1-br, geom->y, br, geom->h); + XSetBackground(ioncore_g.dpy, gc, brc); + XFillRectangle(ioncore_g.dpy, win, gc, geom->x+geom->w-br, geom->y, br, geom->h); geom->w-=br; - }else if(line==GR_BORDERLINE_BOTTOM && geom->w>0){ + }else if(line==GR_BORDERLINE_BOTTOM && geom->w>0 && br>0){ XSetForeground(ioncore_g.dpy, gc, brc); - XDrawRectangle(ioncore_g.dpy, win, gc, geom->x, geom->y+geom->h-1-br, geom->w, br); + XSetBackground(ioncore_g.dpy, gc, brc); + XFillRectangle(ioncore_g.dpy, win, gc, geom->x, geom->y+geom->h-br, geom->w, br); geom->h-=br; } } @@ -222,15 +192,88 @@ void debrush_do_draw_borderline(DEBrush *brush, WRectangle geom, } +void debrush_do_draw_padline(DEBrush *brush, WRectangle geom, + DEColourGroup *cg, GrBorderLine line) +{ + DEBorder *bd=&(brush->d->border); + GC gc=brush->d->normal_gc; + Window win=brush->win; + + draw_borderline(win, gc, &geom, bd->pad, bd->pad, cg->pad, cg->pad, line); +} + + void debrush_draw_borderline(DEBrush *brush, const WRectangle *geom, - const char *attrib, GrBorderLine line) + GrBorderLine line) { - DEColourGroup *cg=debrush_get_colour_group(brush, attrib); + DEColourGroup *cg=debrush_get_current_colour_group(brush); if(cg!=NULL) debrush_do_draw_borderline(brush, *geom, cg, line); } +static void debrush_do_do_draw_border(DEBrush *brush, WRectangle geom, + DEColourGroup *cg) +{ + DEBorder *bd=&(brush->d->border); + GC gc=brush->d->normal_gc; + Window win=brush->win; + + switch(bd->style){ + case DEBORDER_RIDGE: + draw_border(win, gc, &geom, bd->hl, bd->sh, cg->hl, cg->sh); + case DEBORDER_INLAID: + draw_border(win, gc, &geom, bd->pad, bd->pad, cg->pad, cg->pad); + draw_border(win, gc, &geom, bd->sh, bd->hl, cg->sh, cg->hl); + break; + case DEBORDER_GROOVE: + draw_border(win, gc, &geom, bd->sh, bd->hl, cg->sh, cg->hl); + draw_border(win, gc, &geom, bd->pad, bd->pad, cg->pad, cg->pad); + draw_border(win, gc, &geom, bd->hl, bd->sh, cg->hl, cg->sh); + break; + case DEBORDER_ELEVATED: + default: + draw_border(win, gc, &geom, bd->hl, bd->sh, cg->hl, cg->sh); + draw_border(win, gc, &geom, bd->pad, bd->pad, cg->pad, cg->pad); + break; + } +} + + +void debrush_do_draw_border(DEBrush *brush, WRectangle geom, + DEColourGroup *cg) +{ + DEBorder *bd=&(brush->d->border); + + switch(bd->sides){ + case DEBORDER_ALL: + debrush_do_do_draw_border(brush, geom, cg); + break; + case DEBORDER_TB: + debrush_do_draw_padline(brush, geom, cg, GR_BORDERLINE_LEFT); + debrush_do_draw_padline(brush, geom, cg, GR_BORDERLINE_RIGHT); + debrush_do_draw_borderline(brush, geom, cg, GR_BORDERLINE_TOP); + debrush_do_draw_borderline(brush, geom, cg, GR_BORDERLINE_BOTTOM); + break; + case DEBORDER_LR: + debrush_do_draw_padline(brush, geom, cg, GR_BORDERLINE_TOP); + debrush_do_draw_padline(brush, geom, cg, GR_BORDERLINE_BOTTOM); + debrush_do_draw_borderline(brush, geom, cg, GR_BORDERLINE_LEFT); + debrush_do_draw_borderline(brush, geom, cg, GR_BORDERLINE_RIGHT); + break; + } +} + + +void debrush_draw_border(DEBrush *brush, + const WRectangle *geom) +{ + DEColourGroup *cg=debrush_get_current_colour_group(brush); + if(cg!=NULL) + debrush_do_draw_border(brush, *geom, cg); +} + + /*}}}*/ @@ -251,11 +294,43 @@ static void copy_masked(DEBrush *brush, Drawable src, Drawable dst, } + +#define ISSET(S, A) ((S)!=NULL && gr_stylespec_isset(S, A)) + + +GR_DEFATTR(dragged); +GR_DEFATTR(tagged); +GR_DEFATTR(submenu); +GR_DEFATTR(numbered); +GR_DEFATTR(tabnumber); + + +static void ensure_attrs() +{ + GR_ALLOCATTR_BEGIN; + GR_ALLOCATTR(dragged); + GR_ALLOCATTR(tagged); + GR_ALLOCATTR(submenu); + GR_ALLOCATTR(numbered); + GR_ALLOCATTR(tabnumber); + GR_ALLOCATTR_END; +} + + +static int get_ty(const WRectangle *g, const GrBorderWidths *bdw, + const GrFontExtents *fnte) +{ + return (g->y+bdw->top+fnte->baseline + +(g->h-bdw->top-bdw->bottom-fnte->max_height)/2); +} + + void debrush_tab_extras(DEBrush *brush, const WRectangle *g, - DEColourGroup *cg, GrBorderWidths *bdw, - GrFontExtents *fnte, - const char *a1, const char *a2, - bool pre) + DEColourGroup *cg, const GrBorderWidths *bdw, + const GrFontExtents *fnte, + const GrStyleSpec *a1, + const GrStyleSpec *a2, + bool pre, int index) { DEStyle *d=brush->d; GC tmp; @@ -263,20 +338,56 @@ void debrush_tab_extras(DEBrush *brush, const WRectangle *g, * with shared GC:s. */ static bool swapped=FALSE; + + ensure_attrs(); if(pre){ - if(!MATCHES2("*-*-*-dragged", a1, a2)) - return; - - tmp=d->normal_gc; - d->normal_gc=d->stipple_gc; - d->stipple_gc=tmp; - swapped=TRUE; - XClearArea(ioncore_g.dpy, brush->win, g->x, g->y, g->w, g->h, False); + if(ISSET(a2, GR_ATTR(dragged)) || ISSET(a1, GR_ATTR(dragged))){ + tmp=d->normal_gc; + d->normal_gc=d->stipple_gc; + d->stipple_gc=tmp; + swapped=TRUE; + XClearArea(ioncore_g.dpy, brush->win, g->x, g->y, g->w, g->h, False); + } return; } - if(MATCHES2("*-*-tagged", a1, a2)){ + + if((ISSET(a1, GR_ATTR(numbered)) || ISSET(a2, GR_ATTR(numbered))) + && index>=0){ + + DEColourGroup *cg; + GrStyleSpec tmp; + + gr_stylespec_init(&tmp); + gr_stylespec_append(&tmp, a2); + gr_stylespec_set(&tmp, GR_ATTR(tabnumber)); + + cg=debrush_get_colour_group2(brush, a1, &tmp); + + gr_stylespec_unalloc(&tmp); + + if(cg!=NULL){ + char *s=NULL; + + libtu_asprintf(&s, "[%d]", index+1); + + if(s!=NULL){ + int l=strlen(s); + uint w=debrush_get_text_width(brush, s, l); + if(w < g->w-bdw->right-bdw->left){ + int ty=get_ty(g, bdw, fnte); + int tx=(d->textalign==DEALIGN_RIGHT + ? g->x+bdw->left + : g->x+g->w-bdw->right-w); + debrush_do_draw_string(brush, tx, ty, s, l, TRUE, cg); + } + free(s); + } + } + } + + if(ISSET(a2, GR_ATTR(tagged)) || ISSET(a1, GR_ATTR(tagged))){ XSetForeground(ioncore_g.dpy, d->copy_gc, cg->fg); copy_masked(brush, d->tag_pixmap, brush->win, 0, 0, @@ -284,7 +395,7 @@ void debrush_tab_extras(DEBrush *brush, const WRectangle *g, g->x+g->w-bdw->right-d->tag_pixmap_w, g->y+bdw->top); } - + if(swapped){ tmp=d->normal_gc; d->normal_gc=d->stipple_gc; @@ -298,26 +409,29 @@ void debrush_tab_extras(DEBrush *brush, const WRectangle *g, } -void debrush_menuentry_extras(DEBrush *brush, const WRectangle *g, - DEColourGroup *cg, GrBorderWidths *bdw, - GrFontExtents *fnte, - const char *a1, const char *a2, - bool pre) +void debrush_menuentry_extras(DEBrush *brush, + const WRectangle *g, + DEColourGroup *cg, + const GrBorderWidths *bdw, + const GrFontExtents *fnte, + const GrStyleSpec *a1, + const GrStyleSpec *a2, + bool pre, int index) { int tx, ty; if(pre) return; - if(!MATCHES2("*-*-submenu", a1, a2)) - return; - - ty=(g->y+bdw->top+fnte->baseline - +(g->h-bdw->top-bdw->bottom-fnte->max_height)/2); - tx=g->x+g->w-bdw->right; + ensure_attrs(); + + if(ISSET(a2, GR_ATTR(submenu)) || ISSET(a1, GR_ATTR(submenu))){ + ty=get_ty(g, bdw, fnte); + tx=g->x+g->w-bdw->right; - debrush_do_draw_string(brush, tx, ty, DE_SUB_IND, DE_SUB_IND_LEN, - FALSE, cg); + debrush_do_draw_string(brush, tx, ty, DE_SUB_IND, DE_SUB_IND_LEN, + FALSE, cg); + } } @@ -336,10 +450,14 @@ void debrush_do_draw_box(DEBrush *brush, const WRectangle *geom, } -static void debrush_do_draw_textbox(DEBrush *brush, const WRectangle *geom, - const char *text, DEColourGroup *cg, +static void debrush_do_draw_textbox(DEBrush *brush, + const WRectangle *geom, + const char *text, + DEColourGroup *cg, bool needfill, - const char *a1, const char *a2) + const GrStyleSpec *a1, + const GrStyleSpec *a2, + int index) { uint len; GrBorderWidths bdw; @@ -350,7 +468,7 @@ static void debrush_do_draw_textbox(DEBrush *brush, const WRectangle *geom, grbrush_get_font_extents(&(brush->grbrush), &fnte); if(brush->extras_fn!=NULL) - brush->extras_fn(brush, geom, cg, &bdw, &fnte, a1, a2, TRUE); + brush->extras_fn(brush, geom, cg, &bdw, &fnte, a1, a2, TRUE, index); debrush_do_draw_box(brush, geom, cg, needfill); @@ -374,49 +492,55 @@ static void debrush_do_draw_textbox(DEBrush *brush, const WRectangle *geom, tx=geom->x+bdw.left; } - ty=(geom->y+bdw.top+fnte.baseline - +(geom->h-bdw.top-bdw.bottom-fnte.max_height)/2); + ty=get_ty(geom, &bdw, &fnte); debrush_do_draw_string(brush, tx, ty, text, len, FALSE, cg); }while(0); if(brush->extras_fn!=NULL) - brush->extras_fn(brush, geom, cg, &bdw, &fnte, a1, a2, FALSE); + brush->extras_fn(brush, geom, cg, &bdw, &fnte, a1, a2, FALSE, index); } void debrush_draw_textbox(DEBrush *brush, const WRectangle *geom, - const char *text, const char *attr, - bool needfill) + const char *text, bool needfill) { + GrStyleSpec *attr=debrush_get_current_attr(brush); DEColourGroup *cg=debrush_get_colour_group(brush, attr); + if(cg!=NULL){ debrush_do_draw_textbox(brush, geom, text, cg, needfill, - attr, NULL); + attr, NULL, -1); } } void debrush_draw_textboxes(DEBrush *brush, const WRectangle *geom, int n, const GrTextElem *elem, - bool needfill, const char *common_attrib) + bool needfill) { + GrStyleSpec *common_attrib; WRectangle g=*geom; DEColourGroup *cg; GrBorderWidths bdw; int i; + common_attrib=debrush_get_current_attr(brush); + grbrush_get_border_widths(&(brush->grbrush), &bdw); - for(i=0; i0 && needfill){ XClearArea(ioncore_g.dpy, brush->win, g.x, g.y, @@ -490,9 +614,9 @@ void debrush_enable_transparency(DEBrush *brush, GrTransparency mode) } -void debrush_fill_area(DEBrush *brush, const WRectangle *geom, const char *attr) +void debrush_fill_area(DEBrush *brush, const WRectangle *geom) { - DEColourGroup *cg=debrush_get_colour_group(brush, attr); + DEColourGroup *cg=debrush_get_current_colour_group(brush); GC gc=brush->d->normal_gc; if(cg==NULL) @@ -555,9 +679,13 @@ static void debrush_clear_clipping_rectangle(DEBrush *brush) void debrush_begin(DEBrush *brush, const WRectangle *geom, int flags) { + if(flags&GRBRUSH_AMEND) flags|=GRBRUSH_NO_CLEAR_OK; + if(!(flags&GRBRUSH_KEEP_ATTR)) + debrush_init_attr(brush, NULL); + if(!(flags&GRBRUSH_NO_CLEAR_OK)) debrush_clear_area(brush, geom);