about summary refs log tree commit diff stats
path: root/draw.c
blob: a3c526ede838a242392fa05987761669938eb3f8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
 * See LICENSE file for license details.
 */

#include <stdio.h>
#include <string.h>

#include "draw.h"
#include "util.h"

static void
drawborder(Display *dpy, Brush *b)
{
	XPoint points[5];
	XSetLineAttributes(dpy, b->gc, 1, LineSolid, CapButt, JoinMiter);
	XSetForeground(dpy, b->gc, b->border);
	points[0].x = b->rect.x;
	points[0].y = b->rect.y;
	points[1].x = b->rect.width - 1;
	points[1].y = 0;
	points[2].x = 0;
	points[2].y = b->rect.height - 1;
	points[3].x = -(b->rect.width - 1);
	points[3].y = 0;
	points[4].x = 0;
	points[4].y = -(b->rect.height - 1);
	XDrawLines(dpy, b->drawable, b->gc, points, 5, CoordModePrevious);
}

void
draw(Display *dpy, Brush *b, Bool border, const char *text)
{
	unsigned int x, y, w, h, len;
	static char buf[256];
	XGCValues gcv;

	XSetForeground(dpy, b->gc, b->bg);
	XFillRectangles(dpy, b->drawable, b->gc, &b->rect, 1);

	if(border)
		drawborder(dpy, b);

	if(!text)
		return;

	len = strlen(text);
	if(len >= sizeof(buf))
		len = sizeof(buf) - 1;
	memcpy(buf, text, len);
	buf[len] = 0;

	h = b->font.ascent + b->font.descent;
	y = b->rect.y + (b->rect.height / 2) - (h / 2) + b->font.ascent;
	x = b->rect.x + (h / 2);

	/* shorten text if necessary */
	while(len && (w = textwidth_l(&b->font, buf, len)) > b->rect.width - h)
		buf[--len] = 0;

	if(w > b->rect.width)
		return; /* too long */

	gcv.foreground = b->fg;
	gcv.background = b->bg;
	if(b->font.set) {
		XChangeGC(dpy, b->gc, GCForeground | GCBackground, &gcv);
		XmbDrawImageString(dpy, b->drawable, b->font.set, b->gc,
				x, y, buf, len);
	}
	else {
		gcv.font = b->font.xfont->fid;
		XChangeGC(dpy, b->gc, GCForeground | GCBackground | GCFont, &gcv);
		XDrawImageString(dpy, b->drawable, b->gc, x, y, buf, len);
	}
}

static unsigned long
xloadcolors(Display *dpy, Colormap cmap, const char *colstr)
{
	XColor color;
	XAllocNamedColor(dpy, cmap, colstr, &color, &color);
	return color.pixel;
}

void
loadcolors(Display *dpy, int screen, Brush *b,
		const char *bg, const char *fg, const char *border)
{
	Colormap cmap = DefaultColormap(dpy, screen);
	b->bg = xloadcolors(dpy, cmap, bg);
	b->fg = xloadcolors(dpy, cmap, fg);
	b->border = xloadcolors(dpy, cmap, border);
}

unsigned int
textwidth_l(Fnt *font, char *text, unsigned int len)
{
	if(font->set) {
		XRectangle r;
		XmbTextExtents(font->set, text, len, 0, &r);
		return r.width;
	}
	return XTextWidth(font->xfont, text, len);
}

unsigned int
textwidth(Fnt *font, char *text)
{
	return textwidth_l(font, text, strlen(text));
}

void
loadfont(Display *dpy, Fnt *font, const char *fontstr)
{
	char **missing, *def;
	int n;

	missing = NULL;
	def = "?";
	setlocale(LC_ALL, "");
	if(font->set)
		XFreeFontSet(dpy, font->set);
	font->set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
	if(missing) {
		while(n--)
			fprintf(stderr, "missing fontset: %s\n", missing[n]);
		XFreeStringList(missing);
		if(font->set) {
			XFreeFontSet(dpy, font->set);
			font->set = NULL;
		}
	}
	if(font->set) {
		XFontSetExtents *font_extents;
		XFontStruct **xfonts;
		char **font_names;
		unsigned int i;

		font->ascent = font->descent = 0;
		font_extents = XExtentsOfFontSet(font->set);
		n = XFontsOfFontSet(font->set, &xfonts, &font_names);
		for(i = 0, font->ascent = 0, font->descent = 0; i < n; i++) {
			if(font->ascent < (*xfonts)->ascent)
				font->ascent = (*xfonts)->ascent;
			if(font->descent < (*xfonts)->descent)
				font->descent = (*xfonts)->descent;
			xfonts++;
		}
	}
	else {
		if(font->xfont)
			XFreeFont(dpy, font->xfont);
		font->xfont = NULL;
		font->xfont = XLoadQueryFont(dpy, fontstr);
		if (!font->xfont)
			font->xfont = XLoadQueryFont(dpy, "fixed");
		if (!font->xfont)
			error("error, cannot load 'fixed' font\n");
		font->ascent = font->xfont->ascent;
		font->descent = font->xfont->descent;
	}
	font->height = font->ascent + font->descent;
}

unsigned int
labelheight(Fnt *font)
{
	return font->height + 4;
}
pan class="o">= 0x0a0b0c0d; % Reg[3].i = 0x0a0b0c07; # op ModR/M SIB displacement immediate 39 d8 # compare EBX with EAX # ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) +run: compare EBX with r/m32 +run: r/m32 is EAX +run: SF=0; ZF=0; OF=0 :(before "End Single-Byte Opcodes") case 0x39: { // set SF if r/m32 < r32 uint8_t modrm = next(); uint8_t reg2 = (modrm>>3)&0x7; trace(2, "run") << "compare " << rname(reg2) << " with r/m32" << end(); int32_t* arg1 = effective_address(modrm); int32_t arg2 = Reg[reg2].i; int32_t tmp1 = *arg1 - arg2; SF = (tmp1 < 0); ZF = (tmp1 == 0); int64_t tmp2 = *arg1 - arg2; OF = (tmp1 != tmp2); trace(2, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end(); break; } :(scenario compare_r32_with_r32_lesser) % Reg[0].i = 0x0a0b0c07; % Reg[3].i = 0x0a0b0c0d; # op ModR/M SIB displacement immediate 39 d8 # compare EBX with EAX # ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) +run: compare EBX with r/m32 +run: r/m32 is EAX +run: SF=1; ZF=0; OF=0 :(scenario compare_r32_with_r32_equal) % Reg[0].i = 0x0a0b0c0d; % Reg[3].i = 0x0a0b0c0d; # op ModR/M SIB displacement immediate 39 d8 # compare EBX with EAX # ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) +run: compare EBX with r/m32 +run: r/m32 is EAX +run: SF=0; ZF=1; OF=0 //:: copy (mov) :(scenario copy_r32_to_r32) % Reg[3].i = 0xaf; # op ModR/M SIB displacement immediate 89 d8 # copy EBX to EAX # ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) +run: copy EBX to r/m32 +run: r/m32 is EAX +run: storing 0x000000af :(before "End Single-Byte Opcodes") case 0x89: { // copy r32 to r/m32 uint8_t modrm = next(); uint8_t reg2 = (modrm>>3)&0x7; trace(2, "run") << "copy " << rname(reg2) << " to r/m32" << end(); int32_t* arg1 = effective_address(modrm); *arg1 = Reg[reg2].i; trace(2, "run") << "storing 0x" << HEXWORD << *arg1 << end(); break; } //:: xchg :(scenario xchg_r32_with_r32) % Reg[3].i = 0xaf; % Reg[0].i = 0x2e; # op ModR/M SIB displacement immediate 87 d8 # exchange EBX with EAX # ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) +run: exchange EBX with r/m32 +run: r/m32 is EAX +run: storing 0x000000af in r/m32 +run: storing 0x0000002e in EBX :(before "End Single-Byte Opcodes") case 0x87: { // exchange r32 with r/m32 uint8_t modrm = next(); uint8_t reg2 = (modrm>>3)&0x7; trace(2, "run") << "exchange " << rname(reg2) << " with r/m32" << end(); int32_t* arg1 = effective_address(modrm); int32_t tmp = *arg1; *arg1 = Reg[reg2].i; Reg[reg2].i = tmp; trace(2, "run") << "storing 0x" << HEXWORD << *arg1 << " in r/m32" << end(); trace(2, "run") << "storing 0x" << HEXWORD << Reg[reg2].i << " in " << rname(reg2) << end(); break; } //:: push :(scenario push_r32) % Reg[ESP].u = 0x64; % Reg[EBX].i = 0x0000000a; # op ModR/M SIB displacement immediate 53 # push EBX to stack +run: push EBX +run: decrementing ESP to 0x00000060 +run: pushing value 0x0000000a :(before "End Single-Byte Opcodes") case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: { // push r32 to stack uint8_t reg = op & 0x7; trace(2, "run") << "push " << rname(reg) << end(); push(Reg[reg].u); break; } :(code) void push(uint32_t val) { Reg[ESP].u -= 4; trace(2, "run") << "decrementing ESP to 0x" << HEXWORD << Reg[ESP].u << end(); trace(2, "run") << "pushing value 0x" << HEXWORD << val << end(); *reinterpret_cast<uint32_t*>(&Mem.at(Reg[ESP].u)) = val; } //:: pop :(scenario pop_r32) % Reg[ESP].u = 0x60; % SET_WORD_IN_MEM(0x60, 0x0000000a); # op ModR/M SIB displacement immediate 5b # pop stack to EBX +run: pop into EBX +run: popping value 0x0000000a +run: incrementing ESP to 0x00000064 :(before "End Single-Byte Opcodes") case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: { // pop stack into r32 uint8_t reg = op & 0x7; trace(2, "run") << "pop into " << rname(reg) << end(); Reg[reg].u = pop(); break; } :(code) uint32_t pop() { uint32_t result = *reinterpret_cast<uint32_t*>(&Mem.at(Reg[ESP].u)); trace(2, "run") << "popping value 0x" << HEXWORD << result << end(); Reg[ESP].u += 4; trace(2, "run") << "incrementing ESP to 0x" << HEXWORD << Reg[ESP].u << end(); return result; }