Example #1
0
File: crect.c Project: 8l/inferno
void
tkcvsrectdraw(Image *img, TkCitem *i, TkEnv *pe)
{
	int lw, rw;
	TkEnv *e;
	TkCrect *r;
	Rectangle d, rr;
	Point tr, bl;
	Image *pen;

	USED(pe);

	d.min = i->p.drawpt[0];
	d.max = i->p.drawpt[1];

	e = i->env;
	r = TKobj(TkCrect, i);

	pen = nil;
	if((e->set & (1<<TkCfill)))
		pen = tkgc(e, TkCfill);

	if(pen != nil)
		draw(img, d, pen, r->stipple, d.min);

	tr.x = d.max.x;
	tr.y = d.min.y;
	bl.x = d.min.x;
	bl.y = d.max.y;

	rw = (TKF2I(r->width) + 1)/2;
	if(rw <= 0)
		return;
	lw = (TKF2I(r->width))/2;

	pen = tkgc(e, TkCforegnd);
	if(pen != nil) {
		/* horizontal lines first */
		rr.min.x = d.min.x - lw;
		rr.max.x = d.max.x + rw;
		rr.min.y = d.min.y - lw;
		rr.max.y = d.min.y + rw;
		draw(img, rr, pen, nil, rr.min);
		rr.min.y += Dy(d);
		rr.max.y += Dy(d);
		draw(img, rr, pen, nil, rr.min);
		/* now the vertical */
		/* horizontal lines first */
		rr.min.x = d.min.x - lw;
		rr.max.x = d.min.x + rw;
		rr.min.y = d.min.y + rw;
		rr.max.y = d.max.y - lw;
		draw(img, rr, pen, nil, rr.min);
		rr.min.x += Dx(d);
		rr.max.x += Dx(d);
		draw(img, rr, pen, nil, rr.min);
	}
}
Example #2
0
static void
tkentrytext(Image *i, Rectangle s, Tk *tk, TkEnv *env)
{
	TkEntry *tke = TKobj(TkEntry, tk);
	Point dp;
	int s0, s1, xs0, xs1, j;
	Rectangle r;
	Rune showr, *text;

	dp = Pt(s.min.x - (tke->x0 - tke->xv0), s.min.y);
	if (tke->show) {
		chartorune(&showr, tke->show);
		text = mallocz(sizeof(Rune) * (tke->textlen+1), 0);
		if (text == nil)
			return;
		for (j = 0; j < tke->textlen; j++)
			text[j] = showr;
	} else
		text = tke->text;

	runestringn(i, dp, tkgc(env, TkCforegnd), dp, env->font,
				text+tke->v0, tke->v1-tke->v0);

	if (tke->sel0 < tke->v1 && tke->sel1 > tke->v0) {
		if (tke->sel0 < tke->v0) {
			s0 = tke->v0;
			xs0 = tke->xv0 - tke->x0;
		} else {
			s0 = tke->sel0;
			xs0 = tke->xsel0 - tke->x0;
		}

		if (tke->sel1 > tke->v1) {
			s1 = tke->v1;
			xs1 = s.max.x;
		} else {
			s1 = tke->sel1;
			xs1 = tke->xsel1 - tke->x0;
		}

		r = rectaddpt(Rect(xs0, 0, xs1, env->font->height), s.min);
		tktextsdraw(i, r, env, 1);
		runestringn(i, r.min, tkgc(env, TkCselectfgnd), r.min, env->font,
				text+s0, s1-s0);
	}

	if((tke->flag&Ecursoron) && tke->icursor >= tke->v0 && tke->icursor <= tke->v1) {
		r = Rect(
			tke->xicursor - tke->x0, 0, 
			tke->xicursor - tke->x0 + Inswidth, env->font->height
		);
		draw(i, rectaddpt(r, s.min), tkgc(env, TkCforegnd), nil, ZP);
	}
	if (tke->show)
		free(text);
}
Example #3
0
File: cline.c Project: 8l/inferno
void
tkcvslinedraw(Image *img, TkCitem *i, TkEnv *pe)
{
	int w;
	Point *p;
	TkCline *l;
	Image *pen;

	USED(pe);

	l = TKobj(TkCline, i);

	pen = l->pen;
	if(pen == nil)
		pen = tkgc(i->env, TkCforegnd);

	w = TKF2I(l->width)/2;
	if(w < 0)
		return;

	p = i->p.drawpt;
	if(l->smooth == BoolT && i->p.npoint >= 3)
		bezspline(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]);
	else
		poly(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]);
}
Example #4
0
File: label.c Project: 8l/inferno
static void
tktriangle(Point u, Image *i, TkEnv *e)
{	
	Point p[3];

	u.y++;
	p[0].x = u.x + CheckButton;
	p[0].y = u.y + CheckButton/2;
	p[1].x = u.x;
	p[1].y = u.y + CheckButton;
	p[2].x = u.x;
	p[2].y = u.y;
	fillpoly(i, p, 3, ~0, tkgc(e, TkCforegnd), p[0]);
}
Example #5
0
File: scrol.c Project: 8l/inferno
static void
drawslider(TkScroll *tks, Image *i, Point o, int w, int h, TkEnv *e)
{
	Image *l, *d;
	Rectangle r;
	int bgnd;

	bgnd = TkCbackgnd;
	if(tks->flag & (ActiveB1|ButtonB1)) {
		r.min = o;
		r.max.x = o.x + w + Elembw*2;
		r.max.y = o.y + h + Elembw*2;
		bgnd = TkCactivebgnd;
		draw(i, r, tkgc(e, bgnd), nil, ZP);
	}

	l = tkgc(e, bgnd+TkLightshade);
	d = tkgc(e, bgnd+TkDarkshade);
	if(tks->flag & ButtonB1)
		tkbevel(i, o, w, h, Scrollbw, d, l);
	else
		tkbevel(i, o, w, h, Scrollbw, l, d);
}
Example #6
0
File: scrol.c Project: 8l/inferno
static void
drawarrow(TkScroll *tks, Image *i, Point p[3], TkEnv *e, int activef, int buttonf)
{
	Image *l, *d, *t;
	int bgnd;

	bgnd = TkCbackgnd;
	if(tks->flag & (activef|buttonf)) {
		bgnd = TkCactivebgnd;
		fillpoly(i, p, 3, ~0, tkgc(e, bgnd), p[0]);
	}

	l = tkgc(e, bgnd+TkLightshade);
	d = tkgc(e, bgnd+TkDarkshade);
	if(tks->flag & buttonf) {
		t = d;
		d = l;
		l = t;
	}
	line(i, p[1], p[2], 0, 0, Tribw-1, d, p[1]);
	line(i, p[2], p[0], 0, 0, Tribw-1, d, p[2]);
	line(i, p[0], p[1], 0, 0, Tribw-1, l, p[0]);
}
Example #7
0
File: windw.c Project: 8l/inferno
Image*
tkitmp(TkEnv *e, Point p, int fillcol)
{
	Image *i, **ip;
	TkTop *t;
	TkCtxt *ti;
	Display *d;
	Rectangle r;
	ulong pix;
	int alpha;
	
	t = e->top;
	ti = t->ctxt;
	d = t->display;

	pix = e->colors[fillcol];
	alpha = (pix & 0xff) != 0xff;
	ip = alpha ? &ti->ia : &ti->i;

	if(*ip != nil) {
		i = *ip;
		if(p.x <= i->r.max.x && p.y <= i->r.max.y) {
			r.min = ZP;
			r.max = p;
			if (alpha)
				drawop(i, r, nil, nil, ZP, Clear);
			draw(i, r, tkgc(e, fillcol), nil, ZP);
			return i;
		}
		r = i->r;
		freeimage(i);
		if(p.x < r.max.x)
			p.x = r.max.x;
		if(p.y < r.max.y)
			p.y = r.max.y;
	}

	r.min = ZP;
	r.max = p;
	*ip = allocimage(d, r, alpha?RGBA32:d->image->chan, 0, pix);

	return *ip;
}
Example #8
0
char*
tkdrawentry(Tk *tk, Point orig)
{
	Point p;
	TkEnv *env;
	Rectangle r, s;
	Image *i;
	int xp, yp;

	env = tk->env;

	r.min = ZP;
	r.max.x = tk->act.width + 2*tk->borderwidth;
	r.max.y = tk->act.height + 2*tk->borderwidth;
	i = tkitmp(env, r.max, TkCbackgnd);
	if(i == nil)
		return nil;

	xp = tk->borderwidth + xinset(tk);
	yp = tk->borderwidth + yinset(tk);
	s = r;
	s.min.x += xp;
	s.max.x -= xp;
	s.min.y += yp;
	s.max.y -= yp;
	tkentrytext(i, s, tk, env);

	tkdrawrelief(i, tk, ZP, TkCbackgnd, tk->relief);

	if (tkhaskeyfocus(tk))
		tkbox(i, insetrect(r, tk->borderwidth), tk->highlightwidth, tkgc(tk->env, TkChighlightfgnd));

	p.x = tk->act.x + orig.x;
	p.y = tk->act.y + orig.y;
	r = rectaddpt(r, p);
	draw(tkimageof(tk), r, i, nil, ZP);

	return nil;
}
Example #9
0
File: scale.c Project: 8l/inferno
char*
tkdrawscale(Tk *tk, Point orig)
{
	Point p;
	TkEnv *env;
	TkScale *tks;
	Rectangle r, fr;
	Image *i;

	tks = TKobj(TkScale, tk);
	env = tk->env;

	r.min = ZP;
	r.max.x = tk->act.width + 2*tk->borderwidth;
	r.max.y = tk->act.height + 2*tk->borderwidth;
	i = tkitmp(env, r.max, TkCbackgnd);
	if(i == nil)
		return nil;

	if(tks->orient == Tkvertical)
		tkscalevert(tk, i);
	else
		tkscalehoriz(tk, i);

	tkdrawrelief(i, tk, ZP, TkCbackgnd, tk->relief);
	if (tkhaskeyfocus(tk)) {
		fr = insetrect(r, tk->borderwidth);
		tkbox(i, fr, tk->highlightwidth, tkgc(env, TkChighlightfgnd));
	}

	p.x = tk->act.x + orig.x;
	p.y = tk->act.y + orig.y;
	r = rectaddpt(r, p);
	draw(tkimageof(tk), r, i, nil, ZP);

	return nil;
}
Example #10
0
File: ctext.c Project: 8l/inferno
void
tkcvstextdraw(Image *img, TkCitem *i, TkEnv *pe)
{
	TkEnv *e;
	TkCtext *t;
	Point o, dp;
	Rectangle r;
	char *p, *next;
	Image *pen;
	int len, lw, end, start;

	t = TKobj(TkCtext, i);

	e = i->env;
	pen = t->pen;
	if(pen == nil) {
		if (e->set & (1<<TkCfill))
			pen = tkgc(e, TkCfill);
		else
			pen = img->display->black;
	}


	o = addpt(t->anchorp, i->p.drawpt[0]);
	p = t->text;
	while(p && *p) {
		next = tkcvstextgetl(t, e->font, p, &len);
		dp = o;
		if(t->justify != Tkleft) {
			lw = stringnwidth(e->font, p, len);
			if(t->justify == Tkcenter)
				dp.x += (t->pixwidth - lw)/2;
			else
			if(t->justify == Tkright)
				dp.x += t->pixwidth - lw;
		}
		lw = p - t->text;
		if(t->self != -1 && lw+len > t->self) {
			if(t->sell >= t->self) {
				start = t->self - lw;
				end = t->sell - lw;
			}
			else {
				start = t->sell - lw;
				end = t->self - lw;
			}
			if(start < 0)
				r.min.x = o.x;
			else
				r.min.x = dp.x + stringnwidth(e->font, p, start);
			r.min.y = dp.y;
			if(end > len)
				r.max.x = o.x + t->pixwidth;
			else
				r.max.x = dp.x + stringnwidth(e->font, p, end);
			r.max.y = dp.y + e->font->height;
			tktextsdraw(img, r, pe, t->sbw);
			r.max.y = dp.y;
			if(start > 0)
				stringn(img, dp, pen, dp, e->font, p, start);
			if(end > start)
				stringn(img, r.min, tkgc(pe, TkCselectfgnd), r.min, e->font, p+start, end-start);
			if(len > end)
				stringn(img, r.max, pen, r.max, e->font, p+end, len-end);
		}
		else
			stringn(img, dp, pen, dp, e->font, p, len);
		if(t->focus) {
			lw = p - t->text;
			if(t->icursor >= lw && t->icursor <= lw+len) {
				lw = t->icursor - lw;
				if(lw > 0)
					lw = stringnwidth(e->font, p, lw);
				r.min.x = dp.x + lw;
				r.min.y = dp.y - 1;
				r.max.x = r.min.x + 2;
				r.max.y = r.min.y + e->font->height + 1;
				draw(img, r, pen, nil, ZP);
			}
		}
		o.y += e->font->height;
		p = next;
	}
}
Example #11
0
File: canvs.c Project: 8l/inferno
char*
tkdrawcanv(Tk *tk, Point orig)
{
	Image *dst;
	TkCitem *i;
	Display *d;
	TkCanvas *c;
	Rectangle r, bufr, oclipr;
	int vis, alpha, buffer;
	Point rel, p;
	TkCimeth *imeth;

	c = TKobj(TkCanvas, tk);
	d = tk->env->top->display;
	dst = tkimageof(tk);
	/*
	 * translation from local to screen coords
	 */
	rel.x = orig.x + tk->act.x + tk->borderwidth;
	rel.y = orig.y + tk->act.y + tk->borderwidth;

	buffer = c->buffer;
	if (buffer == TkCbufauto)
		buffer = TkCbufvisible;
/*		buffer = (dst == TKobj(TkWin, tk->env->top->root)->image) ? TkCbufvisible : TkCbufnone; */

	if (buffer == TkCbufnone) {
		if(c->image != nil && c->ialloc)
			freeimage(c->image);
		c->image = dst;
		c->ialloc = 0;

		r = tkrect(tk, 0);
		bufr = r;
		rectclip(&bufr, tk->dirty);
		oclipr = dst->clipr;

		replclipr(dst, 0, rectaddpt(bufr, rel));
		draw(dst, rectaddpt(bufr, rel), tkgc(tk->env, TkCbackgnd), nil, ZP);

		p = subpt(rel, c->view);
		p.x = TKI2F(p.x);
		p.y = TKI2F(p.y);
		bufr = rectaddpt(bufr, c->view);
		for(i = c->head; i; i = i->next) {
			if(rectXrect(i->p.bb, bufr)) {
				imeth = &tkcimethod[i->type];
				imeth->coord(i, nil, p.x, p.y);
				imeth->draw(dst, i, tk->env);
				imeth->coord(i, nil, -p.x, -p.y);
			}
		}
		replclipr(dst, 0, oclipr);
	} else {
		if (c->buffer == TkCbufall)
			bufr = c->region;
		else {
			bufr.min = c->view;
			bufr.max.x = c->view.x + tk->act.width;
			bufr.max.y = c->view.y + tk->act.height;
		}
		alpha = (tk->env->colors[TkCbackgnd] & 0xff) != 0xff;
		if(c->image == nil || eqrect(bufr, c->image->r) == 0) {
			if(c->image != nil && c->ialloc)
				freeimage(c->image);
			c->image = allocimage(d, bufr, alpha?RGBA32:d->image->chan, 0, tk->env->colors[TkCbackgnd]);
			c->ialloc = 1;
			c->update = bufr;
			tkcvssetdirty(tk);		/* unnecessary? */
		}
	
		if(c->image == nil)
			return nil;
	
		r = c->update;
		if (rectclip(&r, c->image->r)) {
			if (alpha)
				drawop(c->image, c->update, nil, nil, ZP, Clear);
			draw(c->image, c->update, tkgc(tk->env, TkCbackgnd), nil, c->view);
			replclipr(c->image, 0, r);
			for(i = c->head; i; i = i->next) {
				if(rectXrect(i->p.bb, r))
					tkcimethod[i->type].draw(c->image, i, tk->env);
			}
			replclipr(c->image, 0, c->image->r);
		}
		/*
		 * if the visible area of the canvas image doesn't
		 * fit completely within the dirty rectangle,
		 * then we'll need to draw the background behind it
		 */
		r = tkrect(tk, 0);
		bufr = rectsubpt(bufr, c->view);
		vis = rectclip(&bufr, tkrect(tk, 0));
	
		if (!vis || !rectinrect(tk->dirty, bufr))
			draw(dst, rectaddpt(tk->dirty, rel), tkgc(tk->env, TkCbackgnd), nil, c->view);
	
		if (vis && rectclip(&bufr, tk->dirty))
			draw(dst, rectaddpt(bufr, rel), c->image, nil, addpt(bufr.min, c->view));
	}


	/*
	 * if the border is dirty too, then draw that
	 */
	if (!rectinrect(tk->dirty, bufr)) {
		r.min = addpt(r.min, rel);
		r.min.x -= tk->borderwidth;
		r.min.y -= tk->borderwidth;
		tkdrawrelief(dst, tk, r.min, TkCbackgnd, tk->relief);
	}
	c->update = bbnil;
	return nil;
}
Example #12
0
File: label.c Project: 8l/inferno
/*
 * draw TKlabel, TKseparator, and TKcascade (cascade should really be a button)
 */
char*
tkdrawlabel(Tk *tk, Point orig)
{
 	TkEnv *e;
	TkLabel *tkl;
	Rectangle r, s, mainr, focusr;
	int dx, dy, h;
	Point p, u, v;
	Image *i, *dst, *ct, *img;
	int relief, bgnd, fgnd;

	e = tk->env;

	dst = tkimageof(tk);
	if(dst == nil)
		return nil;

	v.x = tk->act.width + 2*tk->borderwidth;
	v.y = tk->act.height + 2*tk->borderwidth;

	r.min = ZP;
	r.max = v;
	focusr = insetrect(r, tk->borderwidth);
	mainr = insetrect(focusr, tk->highlightwidth);
	relief = tk->relief;

	tkl = TKobj(TkLabel, tk);

	fgnd = TkCforegnd;
	bgnd = TkCbackgnd;
	if (tk->flag & Tkdisabled)
		fgnd = TkCdisablefgnd;
	else if (tk->flag & Tkactive) {
		fgnd = TkCactivefgnd;
		bgnd = TkCactivebgnd;
	}

	i = tkitmp(e, r.max, bgnd);
	if(i == nil)
		return nil;

	if(tk->flag & Tkactive)
		draw(i, r, tkgc(e, bgnd), nil, ZP);

	p = mainr.min;
	h = tkl->h - 2 * tk->highlightwidth;

	dx = tk->act.width - tkl->w - tk->ipad.x;
	dy = tk->act.height - tkl->h - tk->ipad.y;
	if((tkl->anchor & (Tknorth|Tksouth)) == 0)
		p.y += dy/2;
	else if(tkl->anchor & Tksouth)
		p.y += dy;

	if((tkl->anchor & (Tkeast|Tkwest)) == 0)
		p.x += dx/2;
	else if(tkl->anchor & Tkeast)
		p.x += dx;

	if(tk->type == TKcascade) {
		u.x = mainr.max.x - CheckButton - CheckButtonBW;	/* TO DO: CheckButton etc is really the triangle/arrow */
		u.y = p.y + ButtonBorder + (h-CheckSpace)/2;
		tktriangle(u, i, e);
	}

	p.x += tk->ipad.x/2;
	p.y += tk->ipad.y/2;
	u = ZP;

	img = nil;
	if(tkl->img != nil && tkl->img->img != nil)
		img = tkl->img->img;
	else if (tkl->bitmap != nil)
		img = tkl->bitmap;
	if(img != nil) {
		s.min.x = p.x + Bitpadx;
		s.min.y = p.y + Bitpady;
		s.max.x = s.min.x + Dx(img->r);
		s.max.y = s.min.y + Dy(img->r);
		s = rectaddpt(s, u);
		if(tkchanhastype(img->chan, CGrey))
			draw(i, s, tkgc(e, fgnd), img, ZP);
		else
			draw(i, s, img, nil, ZP);
	} else if(tkl->text != nil) {
		u.x += Textpadx;
		u.y += Textpady;
		ct = tkgc(e, fgnd);
		
		p.y += (h - tkl->textheight) / 2;
		tkdrawstring(tk, i, addpt(u, p), tkl->text, tkl->ul, ct, tkl->justify);
	}

	if(tkhaskeyfocus(tk))
		tkbox(i, focusr, tk->highlightwidth, tkgc(e, TkChighlightfgnd));
	tkdrawrelief(i, tk, ZP, bgnd, relief);

	p.x = tk->act.x + orig.x;
	p.y = tk->act.y + orig.y;
	r = rectaddpt(r, p);
	draw(dst, r, i, nil, ZP);

	return nil;
}
Example #13
0
File: scale.c Project: 8l/inferno
static void
tkscalevert(Tk *tk, Image *i)
{
	TkEnv *e;
	TkScale *tks;
	char sv[32];
	Image *d, *l;
	Rectangle r, r2, sr;
	Point p, q;
	int fh, v, sw, gw, w, h, len, sl;
	int fgnd;

	e = tk->env;
	tks = TKobj(TkScale, tk);

	fh = e->font->height;
	fgnd = TkCforegnd;
	if (tk->flag & Tkdisabled)
		fgnd = TkCdisablefgnd;

	r = Rect(0, 0, tk->act.width, tk->act.height);
	r = rectaddpt(r, Pt(tk->borderwidth, tk->borderwidth));
	r = insetrect(r, tk->highlightwidth);
	r = insetrect(r, ScalePad);

	if (tks->sv)
		r.min.x += tks->digwidth + ScalePad;

	if(tks->label != nil) {
		p =  stringsize(e->font, tks->label);
		r.max.x -= p.x;
		string(i, Pt(r.max.x, r.min.y), tkgc(e, fgnd), ZP, e->font, tks->label);
		r.max.x -= ScalePad;
	}

	sr = insetrect(r, ScaleBW);
	h = Dy(sr);
	w = Dx(sr);
	sl = tks->sl + 2*ScaleBW;

	l = tkgc(e, TkCbackgndlght);
	d = tkgc(e, TkCbackgnddark);
	tkbevel(i, r.min, w, h, ScaleBW, d, l);

	tks->pixmin = sr.min.y;
	tks->pixmax = sr.max.y;

	sw = w - 2*ScaleBW;
	tks->sw = sw/2;

	h -= sl;
	if (h <= 0)
		h = 1;
	p.x = sr.max.x;
	p.y = sr.min.y;
	if(tks->tick > 0){
		int j, t, l;
		t = tks->tick;
		l = tks->to-tks->from;
		if (l < 0)
			l = -l;
		if (l == 0)
			l = 1;
		r2.min = p;
		r2.max.x = p.x + ScaleBW + ScalePad;
		for(j = 0; j <= l; j += t){
			r2.min.y = p.y+((vlong)j*h)/l+sl/2;
			r2.max.y = r2.min.y+1;
			draw(i, r2, tkgc(e, fgnd), nil, ZP);
		}
	}

	v = tks->value-tks->from;
	len  = tks->to-tks->from;
	if (len != 0)
		p.y += ((vlong)v*h)/len;
	p.x = sr.min.x;
	q = p;
	if(ScaleBW > 1) {
		q.x++;
		gw = sw;
	} else
		gw = sw-1;
	q.y += tks->sl/2 + 1;
	if(tk->flag & Tkactivated) {
		r2.min = p;
		r2.max.x = sr.max.x;
		r2.max.y = p.y+sl;
		draw(i, r2, tkgc(e, TkCactivebgnd), nil, ZP);
	}
	switch(tks->relief) {
	case TKsunken:
		tkbevel(i, p, sw, tks->sl, ScaleBW, d, l);
		tkbevel(i, q, gw, 0, 1, l, d);
		break;
	case TKraised:
		tkbevel(i, p, sw, tks->sl, ScaleBW, l, d);
		tkbevel(i, q, gw, 0, 1, d, l);
		break;
	}
	tks->pixpos = p.y;
	tks->center = p.x + sw/2 + ScaleBW;

	if(tks->sv != BoolT)
		return;

	tkfprint(sv, tks->value);
	if(tks->digits > 0 && tks->digits < strlen(sv))
		sv[tks->digits] = '\0';

	p.x = r.min.x - ScalePad - stringwidth(e->font, sv);
	p.y = q.y;
	p.y -= fh/2;
	if (p.y < tks->pixmin)
		p.y = tks->pixmin;
	if (p.y + fh > tks->pixmax)
		p.y = tks->pixmax - fh;
	string(i, p, tkgc(e, fgnd), ZP, e->font, sv);
}
Example #14
0
File: scale.c Project: 8l/inferno
static void
tkscalehoriz(Tk *tk, Image *i)
{
	TkEnv *e;
	char sv[32];
	TkScale *tks;
	Image *d, *l;
	Rectangle r, r2, sr;
	Point p, q;
	int fh, sh, gh, sl, v, w, h, len;
	int fgnd;

	e = tk->env;
	tks = TKobj(TkScale, tk);


	fh = e->font->height;
	fgnd = TkCforegnd;
	if (tk->flag & Tkdisabled)
		fgnd = TkCdisablefgnd;

	r = Rect(0, 0, tk->act.width, tk->act.height);
	r = rectaddpt(r, Pt(tk->borderwidth, tk->borderwidth));
	r = insetrect(r, tk->highlightwidth);
	r = insetrect(r, ScalePad);

	if(tks->label != nil) {
		string(i, r.min, tkgc(e, fgnd), ZP, e->font, tks->label);
		r.min.y += fh + ScalePad;
	}
	if(tks->sv == BoolT)
		r.min.y += fh + ScalePad;

	sr = insetrect(r, ScaleBW);
	w = Dx(sr);
	h = Dy(sr);
	sl = tks->sl + 2*ScaleBW;

	l = tkgc(e, TkCbackgndlght);
	d = tkgc(e, TkCbackgnddark);
	tkbevel(i, r.min, w, h, ScaleBW, d, l);

	tks->pixmin = sr.min.x;
	tks->pixmax = sr.max.x;

	sh = h - 2*ScaleBW;
	tks->sw = sh/2;

	w -= sl;
	if (w <= 0)
		w = 1;
	p.x = sr.min.x;
	p.y = sr.max.y;
	if(tks->tick > 0){
		int j, t, l;
		t = tks->tick;
		l = tks->to-tks->from;
		if (l < 0)
			l = -l;
		if (l == 0)
			l = 1;
		r2.min.y = p.y;
		r2.max.y = p.y + ScaleBW + ScalePad;
		for(j = 0; j <= l; j += t){
			r2.min.x = p.x+((vlong)j*w)/l+sl/2;
			r2.max.x = r2.min.x+1;
			draw(i, r2, tkgc(e, fgnd), nil, ZP);
		}
	}
	v = tks->value-tks->from;
	len = tks->to-tks->from;
	if (len != 0)
		p.x += ((vlong)v*w)/len;
	p.y = sr.min.y;
	q = p;
	q.x += tks->sl/2 + 1;
	if(ScaleBW > 1) {
		gh = sh;
		q.y++;
	} else
		gh = sh-1;
	if(tk->flag & Tkactivated) {
		r2.min = p;
		r2.max.x = p.x+sl;
		r2.max.y = sr.max.y;
		draw(i, r2, tkgc(e, TkCactivebgnd), nil, ZP);
	}
	switch(tks->relief) {
	case TKsunken:
		tkbevel(i, p, tks->sl, sh, ScaleBW, d, l);
		tkbevel(i, q, 0, gh, 1, l, d);
		break;
	case TKraised:
		tkbevel(i, p, tks->sl, sh, ScaleBW, l, d);
		tkbevel(i, q, 0, gh, 1, d, l);
		break;
	}
	tks->pixpos = p.x;
	tks->center = p.y + sh/2 + ScaleBW;

	if(tks->sv != BoolT)
		return;

	tkfprint(sv, tks->value);
	if(tks->digits > 0 && tks->digits < strlen(sv))
		sv[tks->digits] = '\0';

	w = stringwidth(e->font, sv);
	p.x = q.x;
	p.x -= w/2;
	p.y = r.min.y - fh - ScalePad;
	if(p.x < tks->pixmin)
		p.x = tks->pixmin;
	if(p.x+w > tks->pixmax)
		p.x = tks->pixmax - w;
	
	string(i, p, tkgc(e, fgnd), ZP, e->font, sv);
}