/* * (C)opyright 2007-2009 Robert Manea * See LICENSE file for license details. * */ #include "dzen.h" #include "action.h" #include #include #include #ifdef DZEN_XPM #include #endif #define ARGLEN 256 #define MAX_ICON_CACHE 32 #define MAX(a,b) ((a)>(b)?(a):(b)) typedef struct ICON_C { char name[ARGLEN]; Pixmap p; int w, h; } icon_c; icon_c icons[MAX_ICON_CACHE]; int icon_cnt; int otx; int xorig=0; /* command types for the in-text parser */ enum ctype {bg, fg, icon, rect, recto, circle, circleo, pos, abspos, titlewin, ibg, fn, fixpos, ca, ba}; struct command_lookup { const char *name; int id; int off; }; struct command_lookup cmd_lookup_table[] = { { "fg(", fg, 3}, { "bg(", bg, 3}, { "i(", icon, 2}, { "r(", rect, 2}, { "ro(", recto, 3}, { "c(", circle, 2}, { "co(", circleo, 3}, { "p(", pos, 2}, { "pa(", abspos, 3}, { "tw(", titlewin, 3}, { "ib(", ibg, 3}, { "fn(", fn, 3}, { "ca(", ca, 3}, { "ba(", ba, 3}, { 0, 0, 0} }; /* positioning helpers */ enum sctype {LOCK_X, UNLOCK_X, TOP, BOTTOM, CENTER, LEFT, RIGHT}; int get_tokval(const char* line, char **retdata); int get_token(const char* line, int * t, char **tval); static unsigned int textnw(Fnt *font, const char *text, unsigned int len) { #ifndef DZEN_XFT XRectangle r; if(font->set) { XmbTextExtents(font->set, text, len, NULL, &r); return r.width; } return XTextWidth(font->xfont, text, len); #else XftTextExtentsUtf8(dzen.dpy, dzen.font.xftfont, (unsigned const char *) text, strlen(text), dzen.font.extents); if(dzen.font.extents->height > dzen.font.height) dzen.font.height = dzen.font.extents->height; return dzen.font.extents->xOff; #endif } void drawtext(const char *text, int reverse, int line, int align) { if(!reverse) { XSetForeground(dzen.dpy, dzen.gc, dzen.norm[ColBG]); XFillRectangle(dzen.dpy, dzen.slave_win.drawable[line], dzen.gc, 0, 0, dzen.w, dzen.h); XSetForeground(dzen.dpy, dzen.gc, dzen.norm[ColFG]); } else { XSetForeground(dzen.dpy, dzen.rgc, dzen.norm[ColFG]); XFillRectangle(dzen.dpy, dzen.slave_win.drawable[line], dzen.rgc, 0, 0, dzen.w, dzen.h); XSetForeground(dzen.dpy, dzen.rgc, dzen.norm[ColBG]); } parse_line(text, line, align, reverse, 0); } long getcolor(const char *colstr) { long color; if ((color = colorcache_get(colstr)) != -1) return color; else { Colormap cmap = DefaultColormap(dzen.dpy, dzen.screen); XColor color; if(!XAllocNamedColor(dzen.dpy, cmap, colstr, &color, &color)) return -1; colorcache_set(colstr, color.pixel); return color.pixel; } } void setfont(const char *fontstr) { #ifndef DZEN_XFT char *def, **missing; int i, n; missing = NULL; if(dzen.font.set) XFreeFontSet(dzen.dpy, dzen.font.set); dzen.font.set = XCreateFontSet(dzen.dpy, fontstr, &missing, &n, &def); if(missing) XFreeStringList(missing); if(dzen.font.set) { XFontSetExtents *font_extents; XFontStruct **xfonts; char **font_names; dzen.font.ascent = dzen.font.descent = 0; font_extents = XExtentsOfFontSet(dzen.font.set); n = XFontsOfFontSet(dzen.font.set, &xfonts, &font_names); for(i = 0, dzen.font.ascent = 0, dzen.font.descent = 0; i < n; i++) { if(dzen.font.ascent < (*xfonts)->ascent) dzen.font.ascent = (*xfonts)->ascent; if(dzen.font.descent < (*xfonts)->descent) dzen.font.descent = (*xfonts)->descent; xfonts++; } } else { if(dzen.font.xfont) XFreeFont(dzen.dpy, dzen.font.xfont); dzen.font.xfont = NULL; if(!(dzen.font.xfont = XLoadQueryFont(dzen.dpy, fontstr))) eprint("dzen: error, cannot load font: '%s'\n", fontstr); dzen.font.ascent = dzen.font.xfont->ascent; dzen.font.descent = dzen.font.xfont->descent; } dzen.font.height = dzen.font.ascent + dzen.font.descent; #else dzen.font.xftfont = XftFontOpenXlfd(dzen.dpy, dzen.screen, fontstr); if(!dzen.font.xftfont) dzen.font.xftfont = XftFontOpenName(dzen.dpy, dzen.screen, fontstr); if(!dzen.font.xftfont) eprint("error, cannot load font: '%s'\n", fontstr); dzen.font.extents = malloc(sizeof(XGlyphInfo)); XftTextExtentsUtf8(dzen.dpy, dzen.font.xftfont, (unsigned const char *) fontstr, strlen(fontstr), dzen.font.extents); dzen.font.height = dzen.font.xftfont->ascent + dzen.font.xftfont->descent; dzen.font.width = (dzen.font.extents->width)/strlen(fontstr); #endif } int get_tokval(const char* line, char **retdata) { int i; char tokval[ARGLEN]; for(i=0; i < ARGLEN && (*(line+i) != ')'); i++) tokval[i] = *(line+i); tokval[i] = '\0'; *retdata = strdup(tokval); return i+1; } int get_token(const char *line, int * t, char **tval) { int off=0, next_pos=0, i; char *tokval = NULL; if(*(line+1) == ESC_CHAR) return 0; line++; for(i=0; cmd_lookup_table[i].name; ++i) { if( off=cmd_lookup_table[i].off, !strncmp(line, cmd_lookup_table[i].name, off) ) { next_pos = get_tokval(line+off, &tokval); *t = cmd_lookup_table[i].id; break; } } *tval = tokval; return next_pos+off; } static void setcolor(Drawable *pm, int x, int width, long tfg, long tbg, int reverse, int nobg) { if(nobg) return; XSetForeground(dzen.dpy, dzen.tgc, reverse ? tfg : tbg); XFillRectangle(dzen.dpy, *pm, dzen.tgc, x, 0, width, dzen.line_height); XSetForeground(dzen.dpy, dzen.tgc, reverse ? tbg : tfg); XSetBackground(dzen.dpy, dzen.tgc, reverse ? tfg : tbg); } int get_sens_area(char *s, int *b, char *cmd) { memset(cmd, 0, 1024); sscanf(s, "%5d", b); char *comma = strchr(s, ','); if (comma != NULL) strncpy(cmd, comma+1, 1024); return 0; } static int get_rect_vals(char *s, int *w, int *h, int *x, int *y) { *w=*h=*x=*y=0; return sscanf(s, "%5dx%5d%5d%5d", w, h, x, y); } static int get_circle_vals(char *s, int *d, int *a) { int ret; *d=*a=ret=0; return sscanf(s, "%5d%5d", d, a); } static int get_pos_vals(char *s, int *d, int *a) { int i=0, ret=3, onlyx=1; char buf[128]; *d=*a=0; if(s[0] == '_') { if(!strncmp(s, "_LOCK_X", 7)) { *d = LOCK_X; } if(!strncmp(s, "_UNLOCK_X", 8)) { *d = UNLOCK_X; } if(!strncmp(s, "_LEFT", 5)) { *d = LEFT; } if(!strncmp(s, "_RIGHT", 6)) { *d = RIGHT; } if(!strncmp(s, "_CENTER", 7)) { *d = CENTER; } if(!strncmp(s, "_BOTTOM", 7)) { *d = BOTTOM; } if(!strncmp(s, "_TOP", 4)) { *d = TOP; } return 5; } else { for(i=0; s[i] && i<128; i++) { if(s[i] == ';') { onlyx=0; break; } else buf[i]=s[i]; } if(i) { buf[i]='\0'; *d=atoi(buf); } else ret=2; if(s[++i]) { *a=atoi(s+i); } else ret = 1; if(onlyx) ret=1; return ret; } } static int get_block_align_vals(char *s, int *a, int *w) { char buf[32]; int r; *w = -1; r = sscanf(s, "%d,%31s", w, buf); if(!strcmp(buf, "_LEFT")) *a = ALIGNLEFT; else if(!strcmp(buf, "_RIGHT")) *a = ALIGNRIGHT; else if(!strcmp(buf, "_CENTER")) *a = ALIGNCENTER; else *a = -1; return r; } static int search_icon_cache(const char* name) { int i; for(i=0; i < MAX_ICON_CACHE; i++) if(!strncmp(icons[i].name, name, ARGLEN)) return i; return -1; } #ifdef DZEN_XPM static void cache_icon(const char* name, Pixmap pm, int w, int h) { if(icon_cnt >= MAX_ICON_CACHE) icon_cnt = 0; if(icons[icon_cnt].p) XFreePixmap(dzen.dpy, icons[icon_cnt].p); strncpy(icons[icon_cnt].name, name, ARGLEN); icons[icon_cnt].w = w; icons[icon_cnt].h = h; icons[icon_cnt].p = pm; icon_cnt++; } #endif char * parse_line(const char *line, int lnr, int align, int reverse, int nodraw) { /* bitmaps */ unsigned int bm_w, bm_h; int bm_xh, bm_yh; /* rectangles, cirlcles*/ int rectw, recth, rectx, recty; /* positioning */ int n_posx, n_posy, set_posy=0; int px=0, py=0, opx=0; int i, next_pos=0, j=0, h=0, tw=0; /* buffer pos */ const char *linep=NULL; /* fonts */ int font_was_set=0; /* position */ int pos_is_fixed = 0; /* block alignment */ int block_align = -1; int block_width = -1; /* clickable area y tracking */ int max_y=-1; /* temp buffers */ char lbuf[MAX_LINE_LEN], *rbuf = NULL; /* parser state */ int t=-1, nobg=0; char *tval=NULL; /* X stuff */ long lastfg = dzen.norm[ColFG], lastbg = dzen.norm[ColBG]; Fnt *cur_fnt = NULL; #ifndef DZEN_XFT XGCValues gcv; #endif Drawable pm=0, bm; #ifdef DZEN_XPM int free_xpm_attrib = 0; Pixmap xpm_pm; XpmAttributes xpma; XpmColorSymbol xpms; #endif #ifdef DZEN_XFT XftDraw *xftd=NULL; XftColor xftc; char *xftcs; int xftcs_f=0; char *xftcs_bg; int xftcs_bgf=0; xftcs = (char *)dzen.fg; xftcs_bg = (char *)dzen.bg; #endif /* icon cache */ int ip; /* parse line and return the text without control commands */ if(nodraw) { rbuf = emalloc(MAX_LINE_LEN); rbuf[0] = '\0'; if( (lnr + dzen.slave_win.first_line_vis) >= dzen.slave_win.tcnt) line = NULL; else line = dzen.slave_win.tbuf[dzen.slave_win.first_line_vis+lnr]; } /* parse line and render text */ else { h = dzen.font.height; py = (dzen.line_height - h) / 2; xorig = 0; if(lnr != -1) { pm = XCreatePixmap(dzen.dpy, RootWindow(dzen.dpy, DefaultScreen(dzen.dpy)), dzen.slave_win.width, dzen.line_height, DefaultDepth(dzen.dpy, dzen.screen)); } else { pm = XCreatePixmap(dzen.dpy, RootWindow(dzen.dpy, DefaultScreen(dzen.dpy)), dzen.title_win.width, dzen.line_height, DefaultDepth(dzen.dpy, dzen.screen)); sens_areas_cnt = 0; } #ifdef DZEN_XFT xftd = XftDrawCreate(dzen.dpy, pm, DefaultVisual(dzen.dpy, dzen.screen), DefaultColormap(dzen.dpy, dzen.screen)); #endif if(!reverse) { XSetForeground(dzen.dpy, dzen.tgc, dzen.norm[ColBG]); #ifdef DZEN_XPM xpms.pixel = dzen.norm[ColBG]; #endif #ifdef DZEN_XFT xftcs_bg = (char *)dzen.bg; xftcs_bgf = 0; #endif } else { XSetForeground(dzen.dpy, dzen.tgc, dzen.norm[ColFG]); #ifdef DZEN_XPM xpms.pixel = dzen.norm[ColFG]; #endif } XFillRectangle(dzen.dpy, pm, dzen.tgc, 0, 0, dzen.w, dzen.h); if(!reverse) { XSetForeground(dzen.dpy, dzen.tgc, dzen.norm[ColFG]); } else { XSetForeground(dzen.dpy, dzen.tgc, dzen.norm[ColBG]); } #ifdef DZEN_XPM xpms.name = NULL; xpms.value = (char *)"none"; xpma.colormap = DefaultColormap(dzen.dpy, dzen.screen); xpma.depth = DefaultDepth(dzen.dpy, dzen.screen); xpma.visual = DefaultVisual(dzen.dpy, dzen.screen); xpma.colorsymbols = &xpms; xpma.numsymbols = 1; xpma.valuemask = XpmColormap|XpmDepth|XpmVisual|XpmColorSymbols; #endif #ifndef DZEN_XFT if(!dzen.font.set){ gcv.font = dzen.font.xfont->fid; XChangeGC(dzen.dpy, dzen.tgc, GCFont, &gcv); } #endif cur_fnt = &dzen.font; if( lnr != -1 && (lnr + dzen.slave_win.first_line_vis >= dzen.slave_win.tcnt)) { XCopyArea(dzen.dpy, pm, dzen.slave_win.drawable[lnr], dzen.gc, 0, 0, px, dzen.line_height, xorig, 0); XFreePixmap(dzen.dpy, pm); return NULL; } } linep = line; while(1) { if(*linep == ESC_CHAR || *linep == '\0') { lbuf[j] = '\0'; /* clear _lock_x at EOL so final width is correct */ if(*linep=='\0') pos_is_fixed=0; if(nodraw) { strcat(rbuf, lbuf); } else { if(t != -1 && tval) { switch(t) { case icon: if(MAX_ICON_CACHE && (ip=search_icon_cache(tval)) != -1) { int y; XCopyArea(dzen.dpy, icons[ip].p, pm, dzen.tgc, 0, 0, icons[ip].w, icons[ip].h, px, y=(set_posy ? py : (dzen.line_height >= (signed)icons[ip].h ? (dzen.line_height - icons[ip].h)/2 : 0))); px += !pos_is_fixed ? icons[ip].w : 0; max_y = MAX(max_y, y+icons[ip].h); } else { int y; if(XReadBitmapFile(dzen.dpy, pm, tval, &bm_w, &bm_h, &bm, &bm_xh, &bm_yh) == BitmapSuccess && (h/2 + px + (signed)bm_w < dzen.w)) { setcolor(&pm, px, bm_w, lastfg, lastbg, reverse, nobg); XCopyPlane(dzen.dpy, bm, pm, dzen.tgc, 0, 0, bm_w, bm_h, px, y=(set_posy ? py : (dzen.line_height >= (int)bm_h ? (dzen.line_height - (int)bm_h)/2 : 0)), 1); XFreePixmap(dzen.dpy, bm); px += !pos_is_fixed ? bm_w : 0; max_y = MAX(max_y, y+bm_h); } #ifdef DZEN_XPM else if(XpmReadFileToPixmap(dzen.dpy, dzen.title_win.win, tval, &xpm_pm, NULL, &xpma) == XpmSuccess) { setcolor(&pm, px, xpma.width, lastfg, lastbg, reverse, nobg); if(MAX_ICON_CACHE) cache_icon(tval, xpm_pm, xpma.width, xpma.height); XCopyArea(dzen.dpy, xpm_pm, pm, dzen.tgc, 0, 0, xpma.width, xpma.height, px, y=(set_posy ? py : (dzen.line_height >= (int)xpma.height ? (dzen.line_height - (int)xpma.height)/2 : 0))); px += !pos_is_fixed ? xpma.width : 0; max_y = MAX(max_y, y+xpma.height); /* freed by cache_icon() */ //XFreePixmap(dzen.dpy, xpm_pm); free_xpm_attrib = 1; } #endif } break; case rect: get_rect_vals(tval, &rectw, &recth, &rectx, &recty); recth = recth > dzen.line_height ? dzen.line_height : recth; if(set_posy) py += recty; recty = recty == 0 ? (dzen.line_height - recth)/2 : (dzen.line_height - recth)/2 + recty; px += !pos_is_fixed ? rectx : 0; setcolor(&pm, px, rectw, lastfg, lastbg, reverse, nobg); XFillRectangle(dzen.dpy, pm, dzen.tgc, px, set_posy ? py : ((int)recty < 0 ? dzen.line_height + recty : recty), rectw, recth); px += !pos_is_fixed ? rectw : 0; break; case recto: get_rect_vals(tval, &rectw, &recth, &rectx, &recty); if (!rectw) break; recth = recth > dzen.line_height ? dzen.line_height-2 : recth-1; if(set_posy) py += recty; recty = recty == 0 ? (dzen.line_height - recth)/2 : (dzen.line_height - recth)/2 + recty; px = (rectx == 0) ? px : rectx+px; /* prevent from stairs effect when rounding recty */ if (!((dzen.line_height - recth) % 2)) recty--; setcolor(&pm, px, rectw, lastfg, lastbg, reverse, nobg); XDrawRectangle(dzen.dpy, pm, dzen.tgc, px, set_posy ? py : ((int)recty<0 ? dzen.line_height + recty : recty), rectw-1, recth); px += !pos_is_fixed ? rectw : 0; break; case circle: rectx = get_circle_vals(tval, &rectw, &recth); setcolor(&pm, px, rectw, lastfg, lastbg, reverse, nobg); XFillArc(dzen.dpy, pm, dzen.tgc, px, set_posy ? py :(dzen.line_height - rectw)/2, rectw, rectw, 90*64, rectx>1?recth*64:64*360); px += !pos_is_fixed ? rectw : 0; break; case circleo: rectx = get_circle_vals(tval, &rectw, &recth); setcolor(&pm, px, rectw, lastfg, lastbg, reverse, nobg); XDrawArc(dzen.dpy, pm, dzen.tgc, px, set_posy ? py : (dzen.line_height - rectw)/2, rectw, rectw, 90*64, rectx>1?recth*64:64*360); px += !pos_is_fixed ? rectw : 0; break; case pos: if(tval[0]) { int r=0; r = get_pos_vals(tval, &n_posx, &n_posy); if( (r == 1 && !set_posy)) set_posy=0; else if (r == 5) { switch(n_posx) { case LOCK_X: pos_is_fixed = 1; break; case UNLOCK_X: pos_is_fixed = 0; break; case LEFT: px = 0; break; case RIGHT: px = dzen.w; break; case CENTER: px = dzen.w/2; break; case BOTTOM: set_posy = 1; py = dzen.line_height; break; case TOP: set_posy = 1; py = 0; break; } } else set_posy=1; if(r != 2) px = px+n_posx<0? 0 : px + n_posx; if(r != 1) py += n_posy; } else { set_posy = 0; py = (dzen.line_height - dzen.font.height) / 2; } break; case abspos: if(tval[0]) { int r=0; if( (r=get_pos_vals(tval, &n_posx, &n_posy)) == 1 && !set_posy) set_posy=0; else set_posy=1; n_posx = n_posx < 0 ? n_posx*-1 : n_posx; if(r != 2) px = n_posx; if(r != 1) py = n_posy; } else { set_posy = 0; py = (dzen.line_height - dzen.font.height) / 2; } break; case ibg: nobg = atoi(tval); break; case bg: lastbg = tval[0] ? (unsigned)getcolor(tval) : dzen.norm[ColBG]; #ifdef DZEN_XFT if(xftcs_bgf) free(xftcs_bg); if(tval[0]) { xftcs_bg = estrdup(tval); xftcs_bgf = 1; } else { xftcs_bg = (char *)dzen.bg; xftcs_bgf = 0; } #endif break; case fg: lastfg = tval[0] ? (unsigned)getcolor(tval) : dzen.norm[ColFG]; XSetForeground(dzen.dpy, dzen.tgc, lastfg); #ifdef DZEN_XFT if(tval[0]) { xftcs = estrdup(tval); xftcs_f = 1; } else { xftcs = (char *)dzen.fg; xftcs_f = 0; } #endif break; case fn: if(tval[0]) { #ifndef DZEN_XFT if(!strncmp(tval, "dfnt", 4)) { cur_fnt = &(dzen.fnpl[atoi(tval+4)]); if(!cur_fnt->set) { gcv.font = cur_fnt->xfont->fid; XChangeGC(dzen.dpy, dzen.tgc, GCFont, &gcv); } } else #endif setfont(tval); } else { cur_fnt = &dzen.font; #ifndef DZEN_XFT if(!cur_fnt->set){ gcv.font = cur_fnt->xfont->fid; XChangeGC(dzen.dpy, dzen.tgc, GCFont, &gcv); } #else setfont(dzen.fnt ? dzen.fnt : FONT); #endif } py = set_posy ? py : (dzen.line_height - cur_fnt->height) / 2; font_was_set = 1; break; case ca: if(lnr == -1) { if(tval[0]) { if(sens_areas_cnt < MAX_CLICKABLE_AREAS) { get_sens_area(tval, &sens_areas[sens_areas_cnt].button, sens_areas[sens_areas_cnt].cmd); sens_areas[sens_areas_cnt].start_x = px; sens_areas[sens_areas_cnt].start_y = py; sens_areas[sens_areas_cnt].end_y = py; max_y = py; sens_areas[sens_areas_cnt].active = 0; sens_areas_cnt++; } } else { /* find most recent unclosed area */ for(i = sens_areas_cnt - 1; i >= 0; i--) if(!sens_areas[i].active) break; if(i >= 0 && i < MAX_CLICKABLE_AREAS) { sens_areas[i].end_x = px; sens_areas[i].end_y = max_y; sens_areas[i].active = 1; } } } break; case ba: if(tval[0]) get_block_align_vals(tval, &block_align, &block_width); else block_align=block_width=-1; break; } free(tval); } /* check if text is longer than window's width */ tw = textnw(cur_fnt, lbuf, strlen(lbuf)); while((((tw + px) > (dzen.w)) || (block_align!=-1 && tw>block_width)) && j>=0) { lbuf[--j] = '\0'; tw = textnw(cur_fnt, lbuf, strlen(lbuf)); } opx = px; /* draw background for block */ if(block_align!=-1 && !nobg) { setcolor(&pm, px, rectw, lastbg, lastbg, 0, nobg); XFillRectangle(dzen.dpy, pm, dzen.tgc, px, 0, block_width, dzen.line_height); } if(block_align==ALIGNRIGHT) px += (block_width - tw); else if(block_align==ALIGNCENTER) px += (block_width/2) - (tw/2); if(!nobg) setcolor(&pm, px, tw, lastfg, lastbg, reverse, nobg); #ifndef DZEN_XFT if(cur_fnt->set) XmbDrawString(dzen.dpy, pm, cur_fnt->set, dzen.tgc, px, py + cur_fnt->ascent, lbuf, strlen(lbuf)); else XDrawString(dzen.dpy, pm, dzen.tgc, px, py+dzen.font.ascent, lbuf, strlen(lbuf)); #else if(reverse) { if (!xftcolorcache_get(xftcs_bg, &xftc)) { XftColorAllocName(dzen.dpy, DefaultVisual(dzen.dpy, dzen.screen), DefaultColormap(dzen.dpy, dzen.screen), xftcs_bg, &xftc); xftcolorcache_set(xftcs_bg, &xftc); } } else { if (!xftcolorcache_get(xftcs, &xftc)) { XftColorAllocName(dzen.dpy, DefaultVisual(dzen.dpy, dzen.screen), DefaultColormap(dzen.dpy, dzen.screen), xftcs, &xftc); xftcolorcache_set(xftcs, &xftc); } } XftDrawStringUtf8(xftd, &xftc, cur_fnt->xftfont, px, py + dzen.font.xftfont->ascent, (const FcChar8 *)lbuf, strlen(lbuf)); if(xftcs_f) { free(xftcs); xftcs_f = 0; } if(xftcs_bgf) { free(xftcs_bg); xftcs_bgf = 0; } #endif max_y = MAX(max_y, py+dzen.font.height); if(block_align==-1) { if(!pos_is_fixed || *linep =='\0') px += tw; } else { if(pos_is_fixed) px = opx; else px = opx+block_width; } block_align=block_width=-1; } if(*linep=='\0') break; j=0; t=-1; tval=NULL; next_pos = get_token(linep, &t, &tval); linep += next_pos; /* ^^ escapes */ if(next_pos == 0) lbuf[j++] = *linep++; } else lbuf[j++] = *linep; linep++; } if(!nodraw) { /* expand/shrink dynamically */ if(dzen.title_win.expand && lnr == -1){ i = px; switch(dzen.title_win.expand) { case left: /* grow left end */ otx = dzen.title_win.x_right_corner - i > dzen.title_win.x ? dzen.title_win.x_right_corner - i : dzen.title_win.x; XMoveResizeWindow(dzen.dpy, dzen.title_win.win, otx, dzen.title_win.y, px, dzen.line_height); break; case right: XResizeWindow(dzen.dpy, dzen.title_win.win, px, dzen.line_height); break; } } else { if(align == ALIGNLEFT) xorig = 0; if(align == ALIGNCENTER) { xorig = (lnr != -1) ? (dzen.slave_win.width - px)/2 : (dzen.title_win.width - px)/2; } else if(align == ALIGNRIGHT) { xorig = (lnr != -1) ? (dzen.slave_win.width - px) : (dzen.title_win.width - px); } } if(lnr != -1) { XCopyArea(dzen.dpy, pm, dzen.slave_win.drawable[lnr], dzen.gc, 0, 0, dzen.w, dzen.line_height, xorig, 0); } else { XCopyArea(dzen.dpy, pm, dzen.title_win.drawable, dzen.gc, 0, 0, dzen.w, dzen.line_height, xorig, 0); } XFreePixmap(dzen.dpy, pm); /* reset font to default */ if(font_was_set) setfont(dzen.fnt ? dzen.fnt : FONT); #ifdef DZEN_XPM if(free_xpm_attrib) { XFreeColors(dzen.dpy, xpma.colormap, xpma.pixels, xpma.npixels, xpma.depth); XpmFreeAttributes(&xpma); } #endif #ifdef DZEN_XFT XftDrawDestroy(xftd); #endif } return nodraw ? rbuf : NULL; } int parse_non_drawing_commands(char * text) { if(!text) return 1; if(!strncmp(text, "^togglecollapse()", strlen("^togglecollapse()"))) { a_togglecollapse(NULL); return 0; } if(!strncmp(text, "^collapse()", strlen("^collapse()"))) { a_collapse(NULL); return 0; } if(!strncmp(text, "^uncollapse()", strlen("^uncollapse()"))) { a_uncollapse(NULL); return 0; } if(!strncmp(text, "^togglestick()", strlen("^togglestick()"))) { a_togglestick(NULL); return 0; } if(!strncmp(text, "^stick()", strlen("^stick()"))) { a_stick(NULL); return 0; } if(!strncmp(text, "^unstick()", strlen("^unstick()"))) { a_unstick(NULL); return 0; } if(!strncmp(text, "^togglehide()", strlen("^togglehide()"))) { a_togglehide(NULL); return 0; } if(!strncmp(text, "^hide()", strlen("^hide()"))) { a_hide(NULL); return 0; } if(!strncmp(text, "^unhide()", strlen("^unhide()"))) { a_unhide(NULL); return 0; } if(!strncmp(text, "^raise()", strlen("^raise()"))) { a_raise(NULL); return 0; } if(!strncmp(text, "^lower()", strlen("^lower()"))) { a_lower(NULL); return 0; } if(!strncmp(text, "^scrollhome()", strlen("^scrollhome()"))) { a_scrollhome(NULL); return 0; } if(!strncmp(text, "^scrollend()", strlen("^scrollend()"))) { a_scrollend(NULL); return 0; } if(!strncmp(text, "^exit()", strlen("^exit()"))) { a_exit(NULL); return 0; } return 1; } void drawheader(const char * text) { if(parse_non_drawing_commands((char *)text)) { if (text){ dzen.w = dzen.title_win.width; dzen.h = dzen.line_height; XFillRectangle(dzen.dpy, dzen.title_win.drawable, dzen.rgc, 0, 0, dzen.w, dzen.h); parse_line(text, -1, dzen.title_win.alignment, 0, 0); } } else { dzen.slave_win.tcnt = -1; dzen.cur_line = 0; } XCopyArea(dzen.dpy, dzen.title_win.drawable, dzen.title_win.win, dzen.gc, 0, 0, dzen.title_win.width, dzen.line_height, 0, 0); } void drawbody(char * text) { char *ec; int i, write_buffer=1; if(dzen.slave_win.tcnt == -1) { dzen.slave_win.tcnt = 0; drawheader(text); return; } if((ec = strstr(text, "^tw()")) && (*(ec-1) != '^')) { dzen.w = dzen.title_win.width; dzen.h = dzen.line_height; XFillRectangle(dzen.dpy, dzen.title_win.drawable, dzen.rgc, 0, 0, dzen.w, dzen.h); parse_line(ec+5, -1, dzen.title_win.alignment, 0, 0); XCopyArea(dzen.dpy, dzen.title_win.drawable, dzen.title_win.win, dzen.gc, 0, 0, dzen.w, dzen.h, 0, 0); return; } if(dzen.slave_win.tcnt == dzen.slave_win.tsize) free_buffer(); write_buffer = parse_non_drawing_commands(text); if(text[0] == '^' && text[1] == 'c' && text[2] == 's') { free_buffer(); for(i=0; i < dzen.slave_win.max_lines; i++) XFillRectangle(dzen.dpy, dzen.slave_win.drawable[i], dzen.rgc, 0, 0, dzen.slave_win.width, dzen.line_height); x_draw_body(); return; } if( write_buffer && (dzen.slave_win.tcnt < dzen.slave_win.tsize) ) { dzen.slave_win.tbuf[dzen.slave_win.tcnt] = estrdup(text); dzen.slave_win.tcnt++; } }