static void draw_picture(control obj, rect r) { image img; bitmap store = NULL; rgb old = currentcolour(); img = obj->img; if (has_transparent_pixels(img)) { store = newbitmap(r.width, r.height, 0); drawto(store); setcolour(getbackground(obj)); fillrect(r); } if (img) { /* Draw the button image. */ if (ischecked(obj)) drawdarker(img, r, getrect(img)); else if (isenabled(obj)) drawimage(img, r, getrect(img)); else drawimage(img, r, getrect(img)); /* never grey */ } if (store != NULL) { drawto(obj); copyrect(store, pt(0,0), getrect(store)); del(store); } setcolour(old); }
static void draw_image_button(button obj, rect r) { image img; bitmap store = NULL; rect ir; rgb up, down; rgb old = currentcolour(); img = obj->img; if (has_transparent_pixels(img)) { store = newbitmap(r.width, r.height, 0); drawto(store); setcolour(getbackground(obj)); fillrect(r); } if (img) { ir = insetr(r,2); if (ishighlighted(obj)) /* button is pressed */ ir.x += 1, ir.y += 1; /* Draw the button image. */ if (ischecked(obj)) drawdarker(img, ir, getrect(img)); else if (isenabled(obj)) drawimage(img, ir, getrect(img)); else drawgreyscale(img, ir, getrect(img)); if (ishighlighted(obj)) { /* fill the gap */ ir.x -= 1, ir.y -= 1; setcolour(getbackground(obj)); drawline(topleft(ir),topright(ir)); drawline(topleft(ir),bottomleft(ir)); } } /* Draw button border. */ setcolour(getforeground(obj)); setlinewidth(1); drawrect(r); /* Draw button shadow. */ up = White, down = Grey; if (ishighlighted(obj)) up = Grey, down = LightGrey; draw_shadow(insetr(r,1), up, down, 1); if (store != NULL) { drawto(obj); copyrect(store, pt(0,0), getrect(store)); del(store); } setcolour(old); }
/* * Private label redraw function. */ static void draw_label(control c, rect r) { /* Draw the label. */ if (!isenabled(c)) setcolour(Grey); else setcolour(Black); setfont(gettextfont(c)); drawtext(r, getvalue(c), getname(c)); }
static void draw_radio(control c, rect r) { int w; rect box, textrect; char *name; int style = (AlignLeft | AlignTop); font f; rgb old = currentcolour(); /* Calculate rectangles. */ f = gettextfont(c); setfont(f); w = strwidth(f,"W"); if (w > r.width) w = r.width; if (w > r.height) w = r.height; box = rect(r.x,r.y+1,w,w); if (w < getheight(f) - getdescent(f)) box.y += getheight(f) - getdescent(f) - w; textrect = rect(r.x+w+w/2,r.y,r.width-(w+w/2),r.height); /* Clear the check area. */ setlinewidth(1); setcolour(White); fillellipse(insetr(box,1)); /* Draw the check area */ if (isenabled(c)) setcolour(Black); else setcolour(Grey); drawellipse(box); /* Provide 'pressed button' effect by black border. */ if (ishighlighted(c)) { setlinewidth(2); drawellipse(box); setlinewidth(1); } /* Put o in circle if checked. */ if (ischecked(c)) fillellipse(insetr(box,3)); name = getname(c); if (isenabled(c)) { /* if (hasfocus(c)) { style |= Underline; setlinewidth(2); } */ setcolour(getforeground(c)); } drawtext(textrect, style, name); setcolour(old); }
/* * Draw a button shadow. */ static void draw_shadow(rect r, rgb col1, rgb col2, int size) { rgb hue = current->hue; /* Draw top-left button border. */ setcolour(col1); fillrect(rect(r.x,r.y,r.width,size)); fillrect(rect(r.x,r.y,size,r.height)); /* Draw bottom-right button border. */ setcolour(col2); while (size > 0) { fillrect(rect(r.x+r.width-1,r.y,1,r.height)); fillrect(rect(r.x,r.y+r.height-1,r.width,1)); r = insetr(r,1); size--; } setcolour(hue); }
static void draw_button(control c, rect r) { rect textrect; rgb up, down; font f; rgb old = currentcolour(); clear(c); /* Draw the button name. */ if (isenabled(c)) setcolour(getforeground(c)); else setcolour(Grey); f = gettextfont(c); setfont(f); textrect = r; if (ishighlighted(c)) textrect.x += 1, textrect.y += 1; drawtext(textrect, Center|VCenter, getname(c)); /* Draw button border. */ setlinewidth(1); drawrect(r); r = insetr(r,1); /* Draw button shadow. */ up = White, down = Grey; if (ishighlighted(c)) up = Grey, down = LightGrey; else if (hasfocus(c)) { setcolour(Black); drawrect(r); r = insetr(r,1); } draw_shadow(r, up, down, SHADOW_WIDTH); setcolour(old); }
int render_line(int buf, int uline) { if(bufs[buf].lpt[uline]) { int pline; for(pline=0;pline<bufs[buf].lpl[uline];pline++) free(bufs[buf].lpt[uline][pline]); free(bufs[buf].lpt[uline]); } if( // this is quite a complicated conditional, so I've split it up. It handles conference mode, quiet mode and debug mode (bufs[buf].conf&&( (bufs[buf].lm[uline]==JOIN) ||(bufs[buf].lm[uline]==PART) ||(bufs[buf].lm[uline]==NICK) ||(bufs[buf].lm[uline]==MODE) ||(bufs[buf].lm[uline]==QUIT) ) ) || (quiet&&(bufs[buf].lq[uline]==QUIET)) || (!debug&&(bufs[buf].lq[uline]==DEBUG)) ) { bufs[buf].lpt[uline]=NULL; bufs[buf].lpl[uline]=0; return(0); } char *tag=strdup(bufs[buf].ltag[uline]?bufs[buf].ltag[uline]:""); bool mergetype=((bufs[buf].lm[uline]==JOIN)&&*tag)||(bufs[buf].lm[uline]==PART)||(bufs[buf].lm[uline]==QUIT); bool merged=false; if(merge&&(bufs[buf].type==CHANNEL)&&mergetype) { int prevline=uline; while(1) { if(--prevline<0) { prevline+=bufs[buf].nlines; if(!bufs[buf].filled) break; } if(fabs(difftime(bufs[buf].ts[prevline], bufs[buf].ts[uline]))>5) break; if(bufs[buf].lm[prevline]==bufs[buf].lm[uline]) { if((bufs[buf].lm[uline]==QUIT)&&strcmp(bufs[buf].lt[uline], bufs[buf].lt[prevline])) break; const char *ltag=bufs[buf].ltag[prevline]; if(!ltag) ltag=""; if((bufs[buf].lm[uline]==JOIN)&&!*ltag) break; size_t nlen=strlen(tag)+strlen(ltag)+2; char *ntag=malloc(nlen); snprintf(ntag, nlen, "%s=%s", ltag, tag); free(tag); tag=ntag; int pline; for(pline=0;pline<bufs[buf].lpl[prevline];pline++) free(bufs[buf].lpt[prevline][pline]); free(bufs[buf].lpt[prevline]); bufs[buf].lpt[prevline]=NULL; bufs[buf].lpl[prevline]=0; merged=true; continue; } break; } } char *message=strdup(bufs[buf].lt[uline]); char *proc;size_t l,i; init_char(&proc, &l, &i); char stamp[STAMP_LEN]; timestamp(stamp, bufs[buf].ts[uline]); colour c={.fore=7, .back=0, .hi=false, .ul=false}; switch(bufs[buf].lm[uline]) { case MSG: { c=c_msg[bufs[buf].ls[uline]?0:1]; char mk[6]="<%s> "; if(show_prefix&&bufs[buf].lp[uline]) { mk[0]=mk[3]=bufs[buf].lp[uline]; } crush(&tag, maxnlen); char *ntag=mktag(mk, tag); free(tag); tag=ntag; } break; case NOTICE: { c=c_notice[bufs[buf].ls[uline]?0:1]; if(*tag) { crush(&tag, maxnlen); char *ntag=mktag("(%s) ", tag); free(tag); tag=ntag; } } break; case PREFORMAT: c=c_notice[bufs[buf].ls[uline]?0:1]; break; case ACT: { c=c_actn[bufs[buf].ls[uline]?0:1]; crush(&tag, maxnlen); char *ntag=mktag("* %s ", tag); free(tag); tag=ntag; } break; case JOIN: c=c_join[bufs[buf].ls[uline]?0:1]; if(tag&&*tag) { free(message); const char *bn=bufs[buf].bname; if(!bn) bn="the channel"; size_t l=16+strlen(bn); message=malloc(l); if(merged) snprintf(message, l, "have joined %s", bufs[buf].bname); else snprintf(message, l, "has joined %s", bufs[buf].bname); } goto eqtag; case PART: c=c_part[bufs[buf].ls[uline]?0:1]; if(tag&&*tag) { free(message); const char *bn=bufs[buf].bname; if(!bn) bn="the channel"; size_t l=16+strlen(bn); message=malloc(l); if(merged) snprintf(message, l, "have left %s", bufs[buf].bname); else snprintf(message, l, "has left %s", bufs[buf].bname); } goto eqtag; case QUIT: c=c_quit[bufs[buf].ls[uline]?0:1]; if(tag&&*tag) { const char *bn=bufs[buf].bname; if(!bn) bn="the channel"; size_t l=16+strlen(bn)+strlen(message); char *nmessage=malloc(l); if(merged) snprintf(nmessage, l, "have left %s (%s)", bufs[buf].bname, message); else snprintf(nmessage, l, "has left %s (%s)", bufs[buf].bname, message); free(message); message=nmessage; } goto eqtag; case QUIT_PREFORMAT: c=c_quit[bufs[buf].ls[uline]?0:1]; break; case NICK: { c=c_nick[bufs[buf].ls[uline]?0:1]; eqtag: if(!merge) crush(&tag, maxnlen); char *ntag=mktag("=%s= ", tag); free(tag); tag=ntag; } break; case MODE: c=c_nick[bufs[buf].ls[uline]?0:1]; break; case STA: c=c_status; break; case ERR: c=c_err; break; case UNK: c=c_unk; break; case UNK_NOTICE: c=c_unk; if(*tag) { crush(&tag, maxnlen); char *ntag=mktag("(%s) ", tag); free(tag); tag=ntag; } break; case UNN: c=c_unn; break; default: break; } int x=wordline(stamp, 0, &proc, &l, &i, c); x=wordline(tag, indent?x:0, &proc, &l, &i, c); free(tag); wordline(message, indent?x:0, &proc, &l, &i, c); free(message); bufs[buf].lpl[uline]=0; bufs[buf].lpt[uline]=NULL; bufs[buf].lpc[uline]=c; char *curr=strtok(proc, "\n"); while(curr) { int pline=bufs[buf].lpl[uline]++; char **nlpt=realloc(bufs[buf].lpt[uline], bufs[buf].lpl[uline]*sizeof(char *)); if(!nlpt) { add_to_buffer(0, ERR, NORMAL, 0, false, "realloc failed; buffer may be corrupted", "render_buffer: "); free(proc); return(1); } (bufs[buf].lpt[uline]=nlpt)[pline]=strdup(curr); curr=strtok(NULL, "\n"); } free(proc); return(0); } void in_update(iline inp) { height=max(height, 5); // anything less than this is /silly/ width=max(width, 30); // widths less than 30 break things, and are /also silly/ resetcol(); locate(height-1, 1); // tab strip int mbw = (width-1)/nbufs; if(mbw>1) { int b; for(b=0;b<nbufs;b++) { colour c={7, hilite_tabstrip?5:0, false, false}; setcolour(c); putchar(' '); // (status) {server} [channel] <user> char brack[2]={'!', '!'}; switch(bufs[b].type) { case STATUS: brack[0]='(';brack[1]=')'; break; case SERVER: brack[0]='{';brack[1]='}'; break; case CHANNEL: brack[0]='[';brack[1]=']'; break; case PRIVATE: brack[0]='<';brack[1]='>'; break; } if(b==cbuf) { c.back=2; // green c.hi=true; } else if(b==bufs[cbuf].server) { c.back=4; // blue c.ul=true; } if(bufs[b].hi_alert%2) { c.fore=6; // cyan c.hi=true; } else if(bufs[b].alert) { c.fore=1; // red c.hi=true; } if((!LIVE(b)) && (c.fore!=6)) { c.fore=3; // yellow c.hi=true; } setcolour(c); putchar(brack[0]); if(mbw>3) { char *tab=strdup(bufs[b].bname); if(bufs[b].type==SERVER) { scrush(&tab, mbw-3); } else { crush(&tab, mbw-3); } printf("%s", tab); free(tab); } if(mbw>2) putchar(brack[1]); c.fore=7; c.back=hilite_tabstrip?5:0; c.hi=c.ul=false; setcolour(c); } } else { setcolour((colour){.fore=0, .back=1, .hi=true, .ul=false}); printf("buf %u [0 to %u]", cbuf, nbufs-1); }