最適化

This commit is contained in:
2026-01-17 23:52:07 +09:00
parent c6f2982855
commit 5f5f8248d8
11 changed files with 217 additions and 176 deletions

View File

@@ -14,9 +14,11 @@ VERSION != cat main.c | grep "const char \*version" | awk '{print $$5}' |\
PREFIX = /usr/local PREFIX = /usr/local
# cc | clang | gcc
CC = cc CC = cc
# lldb | gdb
DEBUGGER = lldb
FILES = main.c src/*.c FILES = main.c src/*.c
# FILES = main.c
CFLAGS = -Wall -Wextra \ CFLAGS = -Wall -Wextra \
-I./dep/include -I/usr/include -I/usr/local/include -I/usr/X11R6/include \ -I./dep/include -I/usr/include -I/usr/local/include -I/usr/X11R6/include \
@@ -31,7 +33,7 @@ all: debug
debug: debug:
${CC} -O0 -g ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS} ${CC} -O0 -g ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS}
lldb -o run ${NAME} ${DEBUGGER} -o run ${NAME}
develop: develop:
${CC} -O3 -g ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS} ${SLIB} ${CC} -O3 -g ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS} ${SLIB}

View File

@@ -1,19 +1,19 @@
# Unix Calc # Unix Calc
XLibre向け電卓。 XLibre向け電卓。\
Xorg以外、従属ライブラリを使いません。 Xorg以外、従属ライブラリを使いません。
## インストールする方法 | Installation ## インストールする方法 | Installation
### BSD ### BSD
```sh ```sh
make make
doas make install doas make install release
``` ```
### Linux ### Linux
```sh ```sh
make make
doas bmake install doas bmake install release
``` ```
![](scrot1.png)\ ![](scrot1.png)\

119
main.c
View File

@@ -10,6 +10,9 @@ const char *disname = "Unix Calc";
int main() { int main() {
UiSystem ui; UiSystem ui;
ui.isrunning = 1;
ui.window.width = 382;
ui.window.height = 534;
XEvent event; XEvent event;
int screen; int screen;
XGCValues values; XGCValues values;
@@ -24,33 +27,36 @@ int main() {
int sw = DisplayWidth(ui.display, screen); int sw = DisplayWidth(ui.display, screen);
int sh = DisplayHeight(ui.display, screen); int sh = DisplayHeight(ui.display, screen);
int window_x = (sw - window_width) / 3; ui.window.x = (sw - ui.window.width) / 3;
int window_y = (sh - window_height) / 2; ui.window.y = (sh - ui.window.height) / 2;
ui.window = XCreateSimpleWindow(ui.display, ui.xwindow = XCreateSimpleWindow(ui.display,
RootWindow(ui.display, screen), RootWindow(ui.display, screen),
window_x, window_y, window_width, window_height, 1, BTCOL, BGCOL); ui.window.x, ui.window.y,
if (!ui.window) { ui.window.width, ui.window.height,
1, BTCOL, BGCOL);
if (!ui.xwindow) {
cleanup(&ui); cleanup(&ui);
fprintf(stderr, "ウィンドウを作成に失敗。\n"); fprintf(stderr, "ウィンドウを作成に失敗。\n");
exit(1); exit(1);
} }
ui.backbuf = XCreatePixmap(ui.display, ui.window, window_width, window_height, ui.backbuf = XCreatePixmap(ui.display, ui.xwindow,
ui.window.width, ui.window.height,
DefaultDepth(ui.display, screen)); DefaultDepth(ui.display, screen));
ui.target = ui.backbuf; ui.target = ui.backbuf;
Atom net_wm_window_type = XInternAtom(ui.display, "_NET_WM_WINDOW_TYPE", False); Atom net_wm_window_type = XInternAtom(ui.display, "_NET_WM_WINDOW_TYPE", False);
Atom dialog = XInternAtom(ui.display, "_NET_WM_WINDOW_TYPE_DIALOG", False); Atom dialog = XInternAtom(ui.display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
XChangeProperty(ui.display, ui.window, net_wm_window_type, XA_ATOM, 32, XChangeProperty(ui.display, ui.xwindow, net_wm_window_type, XA_ATOM, 32,
PropModeReplace, (unsigned char *)&dialog, 1); PropModeReplace, (unsigned char *)&dialog, 1);
XStoreName(ui.display, ui.window, disname); XStoreName(ui.display, ui.xwindow, disname);
Atom net_wm_name = XInternAtom(ui.display, "_NET_WM_NAME", False); Atom net_wm_name = XInternAtom(ui.display, "_NET_WM_NAME", False);
char displayname[16]; char displayname[16];
snprintf(displayname, 16, "%s %s", disname, version); snprintf(displayname, 16, "%s %s", disname, version);
XChangeProperty(ui.display, ui.window, net_wm_name, XChangeProperty(ui.display, ui.xwindow, net_wm_name,
XInternAtom(ui.display, "UTF8_STRING", False), 8, XInternAtom(ui.display, "UTF8_STRING", False), 8,
PropModeReplace, (unsigned char *)displayname, strlen(displayname)); PropModeReplace, (unsigned char *)displayname, strlen(displayname));
@@ -58,13 +64,13 @@ int main() {
if (classHint) { if (classHint) {
classHint->res_name = "unixcalc"; classHint->res_name = "unixcalc";
classHint->res_class = "UnixCalc"; classHint->res_class = "UnixCalc";
XSetClassHint(ui.display, ui.window, classHint); XSetClassHint(ui.display, ui.xwindow, classHint);
XFree(classHint); XFree(classHint);
} }
XSetWindowBackground(ui.display, ui.window, BGCOL); XSetWindowBackground(ui.display, ui.xwindow, BGCOL);
XSelectInput(ui.display, ui.window, XSelectInput(ui.display, ui.xwindow,
ExposureMask ExposureMask
| ButtonPressMask | ButtonPressMask
| ButtonReleaseMask | ButtonReleaseMask
@@ -74,7 +80,7 @@ int main() {
// | StructureNotifyMask // | StructureNotifyMask
); );
ui.gc = XCreateGC(ui.display, ui.window, 0, &values); ui.gc = XCreateGC(ui.display, ui.xwindow, 0, &values);
if (!ui.gc) { if (!ui.gc) {
cleanup(&ui); cleanup(&ui);
fprintf(stderr, "GCを作成に失敗。\n"); fprintf(stderr, "GCを作成に失敗。\n");
@@ -83,13 +89,74 @@ int main() {
ui.visual = *DefaultVisual(ui.display, screen); ui.visual = *DefaultVisual(ui.display, screen);
ui.colormap = XCreateColormap(ui.display, ui.window, &ui.visual, AllocNone); ui.colormap = XCreateColormap(ui.display, ui.xwindow, &ui.visual, AllocNone);
if (ui.colormap == None) { if (ui.colormap == None) {
cleanup(&ui); cleanup(&ui);
fprintf(stderr, "カラーマップを作成に失敗。\n"); fprintf(stderr, "カラーマップを作成に失敗。\n");
exit(1); exit(1);
} }
XWindowAttributes attr;
XGetWindowAttributes(ui.display, ui.xwindow, &attr);
int w = attr.width;
{
ui.resLabel.font = XftFontOpenName(ui.display, screen, "Noto Sans CJK-72");
if (!ui.resLabel.font) {
cleanup(&ui);
fprintf(stderr, "解決フォントの読み込みに失敗。\n");
exit(1);
}
ui.resLabel.text[0] = '0';
ui.resLabel.text[1] = '\0';
const FcChar8 *text = (const FcChar8 *)ui.resLabel.text;
int len = strlen((const char *)text);
XGlyphInfo extents;
XftTextExtentsUtf8(ui.display, ui.resLabel.font, text, len, &extents);
ui.resLabel.x = w - 20 - extents.xOff;
ui.resLabel.y = 180;
if (!XftColorAllocName(ui.display,
DefaultVisual(ui.display, DefaultScreen(ui.display)),
DefaultColormap(ui.display, DefaultScreen(ui.display)),
"#ee4030", &ui.resLabel.fg_color)) {
cleanup(&ui);
fprintf(stderr, "色の役割に失敗。\n");
exit(1);
}
}
{
ui.problemLabel.font = XftFontOpenName(ui.display, screen, "Noto Sans CJK-24");
if (!ui.problemLabel.font) {
cleanup(&ui);
fprintf(stderr, "問題フォントの読み込みに失敗。\n");
exit(1);
}
ui.problemLabel.text[0] = '\0';
const FcChar8 *text = (const FcChar8 *)ui.problemLabel.text;
int len = strlen((const char *)text);
XGlyphInfo extents;
XftTextExtentsUtf8(ui.display, ui.problemLabel.font, text, len, &extents);
ui.problemLabel.x = w - 20 - extents.xOff;
ui.problemLabel.y = 80;
if (!XftColorAllocName(ui.display,
DefaultVisual(ui.display, DefaultScreen(ui.display)),
DefaultColormap(ui.display, DefaultScreen(ui.display)),
"#b61729", &ui.problemLabel.fg_color)) {
cleanup(&ui);
fprintf(stderr, "色の役割に失敗。\n");
exit(1);
}
}
ui.font = XftFontOpenName(ui.display, screen, "Noto Sans CJK-12"); ui.font = XftFontOpenName(ui.display, screen, "Noto Sans CJK-12");
if (!ui.font) { if (!ui.font) {
cleanup(&ui); cleanup(&ui);
@@ -97,44 +164,30 @@ int main() {
exit(1); exit(1);
} }
ui.prbfont = XftFontOpenName(ui.display, screen, "Noto Sans CJK-24");
if (!ui.prbfont) {
cleanup(&ui);
fprintf(stderr, "問題フォントの読み込みに失敗。\n");
exit(1);
}
ui.disfont = XftFontOpenName(ui.display, screen, "Noto Sans CJK-72");
if (!ui.disfont) {
cleanup(&ui);
fprintf(stderr, "解決フォントの読み込みに失敗。\n");
exit(1);
}
if (!XftColorAllocName(ui.display, &ui.visual, ui.colormap, "#232020", &ui.color)) { if (!XftColorAllocName(ui.display, &ui.visual, ui.colormap, "#232020", &ui.color)) {
cleanup(&ui); cleanup(&ui);
fprintf(stderr, "色の役割に失敗。\n"); fprintf(stderr, "色の役割に失敗。\n");
exit(1); exit(1);
} }
XMapWindow(ui.display, ui.window); XMapWindow(ui.display, ui.xwindow);
{ {
XWindowAttributes attr; XWindowAttributes attr;
XGetWindowAttributes(ui.display, ui.window, &attr); XGetWindowAttributes(ui.display, ui.xwindow, &attr);
XEvent fake = { .type = Expose }; XEvent fake = { .type = Expose };
fake.xexpose.window = ui.window; fake.xexpose.window = ui.xwindow;
fake.xexpose.width = attr.width; fake.xexpose.width = attr.width;
fake.xexpose.height = attr.height; fake.xexpose.height = attr.height;
control_expose(&ui, &event); control_expose(&ui, &event);
} }
while (isrunning) { while (ui.isrunning) {
XNextEvent(ui.display, &event); XNextEvent(ui.display, &event);
switch (event.type) { switch (event.type) {
case Expose: case Expose:
case ConfigureNotify: case ConfigureNotify:
XClearWindow(ui.display, ui.window); XClearWindow(ui.display, ui.xwindow);
control_expose(&ui, &event); control_expose(&ui, &event);
break; break;
case ButtonPress: case ButtonPress:

View File

@@ -4,7 +4,11 @@
#include "control.h" #include "control.h"
#include "display.h" #include "display.h"
#include "program.h"
char curinput[64] = {0};
int input_pos = 0;
int initialized = 0;
XftColor buttonColor;
static const char *btn_labels[][10] = { static const char *btn_labels[][10] = {
{ NULL }, // 数字表示 { NULL }, // 数字表示
@@ -16,7 +20,7 @@ static const char *btn_labels[][10] = {
}; };
#define NUM_ROWS 6 #define NUM_ROWS 6
#define NUM_COLS 6 #define NUM_COLS 4
static SuwaButton *find_button_at(int mx, int my) { static SuwaButton *find_button_at(int mx, int my) {
static SuwaButton found = {0}; static SuwaButton found = {0};
@@ -52,35 +56,35 @@ static SuwaButton *find_button_at(int mx, int my) {
found.y = 224 + (row - 1) * (btn_h + padding); found.y = 224 + (row - 1) * (btn_h + padding);
found.width = btn_w; found.width = btn_w;
found.height = btn_h; found.height = btn_h;
found.label = btn_labels[row][col]; found.text = btn_labels[row][col];
found.pressed = 1; found.pressed = 1;
return &found; return &found;
} }
void append_to_input(char c) { void append_to_input(UiSystem *ui, char c) {
if ((unsigned long)input_pos >= sizeof(curinput) - 2) return; if ((unsigned long)input_pos >= sizeof(curinput) - 2) return;
strcpy(displayprb, ""); strcpy(ui->problemLabel.text, "");
curinput[input_pos++] = c; curinput[input_pos++] = c;
curinput[input_pos] = '\0'; curinput[input_pos] = '\0';
strncpy(displaytxt, curinput, sizeof(displaytxt) - 1); strncpy(ui->resLabel.text, curinput, sizeof(ui->resLabel.text) - 1);
displaytxt[sizeof(displaytxt) - 1] = '\0'; ui->resLabel.text[sizeof(ui->resLabel.text) - 1] = '\0';
} }
void clear_calculator(void) { void clear_calculator(UiSystem *ui) {
strcpy(displayprb, ""); strcpy(ui->problemLabel.text, "");
curinput[0] = '\0'; curinput[0] = '\0';
input_pos = 0; input_pos = 0;
strcpy(displaytxt, "0"); strcpy(ui->resLabel.text, "0");
} }
double evaluate_simple(const char *expr) { double evaluate_simple(UiSystem *ui, const char *expr) {
double res = 0.0; double res = 0.0;
double cur = 0.0; double cur = 0.0;
char op = '+'; char op = '+';
int i = 0; int i = 0;
snprintf(displayprb, sizeof(displayprb), "%s=", expr); snprintf(ui->problemLabel.text, sizeof(ui->problemLabel.text), "%s=", expr);
while (expr[i]) { while (expr[i]) {
if (expr[i] == ' ') { i++; continue; } if (expr[i] == ' ') { i++; continue; }
@@ -124,7 +128,7 @@ void control_expose(UiSystem *ui, XEvent *e) {
if (e->type != Expose && e->type != ConfigureNotify) return; if (e->type != Expose && e->type != ConfigureNotify) return;
XWindowAttributes attr; XWindowAttributes attr;
XGetWindowAttributes(ui->display, ui->window, &attr); XGetWindowAttributes(ui->display, ui->xwindow, &attr);
int w = attr.width; int w = attr.width;
int h = attr.height; int h = attr.height;
@@ -133,12 +137,12 @@ void control_expose(UiSystem *ui, XEvent *e) {
ui->backbuf = None; ui->backbuf = None;
} }
ui->backbuf = XCreatePixmap(ui->display, ui->window, w, h, ui->backbuf = XCreatePixmap(ui->display, ui->xwindow, w, h,
DefaultDepth(ui->display, DefaultScreen(ui->display))); DefaultDepth(ui->display, DefaultScreen(ui->display)));
if (ui->backbuf == None) { if (ui->backbuf == None) {
fprintf(stderr, "バックバッファ作成失敗!\n"); fprintf(stderr, "バックバッファ作成失敗!\n");
ui->backbuf = ui->window; ui->backbuf = ui->xwindow;
} }
ui->target = ui->backbuf; ui->target = ui->backbuf;
@@ -157,80 +161,73 @@ void control_expose(UiSystem *ui, XEvent *e) {
XFillRectangle(ui->display, ui->backbuf, ui->gc, 0, 0, w, h); XFillRectangle(ui->display, ui->backbuf, ui->gc, 0, 0, w, h);
// 出力 // 出力
if (displaytxt[0] != '\0' && ui->disfont) { {
const FcChar8 *text = (const FcChar8 *)displaytxt;
int len = strlen((const char *)text);
XGlyphInfo extents; XGlyphInfo extents;
XftTextExtentsUtf8(ui->display, ui->disfont, text, len, &extents); XftTextExtentsUtf8(ui->display, ui->resLabel.font,
(const FcChar8 *)ui->resLabel.text,
strlen(ui->resLabel.text), &extents);
int tx = w - 20 - extents.xOff; int tx = w - 20 - extents.xOff;
int ty = 160;
XftColor discol; XftDrawStringUtf8(
XftColorAllocName(ui->display, DefaultVisual(ui->display, DefaultScreen(ui->display)), backdraw, &ui->resLabel.fg_color, ui->resLabel.font,
DefaultColormap(ui->display, DefaultScreen(ui->display)), tx, ui->resLabel.y,
"#ee4030", &discol); (const FcChar8 *)ui->resLabel.text, 32);
XftDrawStringUtf8(backdraw, &discol, ui->disfont, tx, ty, text, len);
XftColorFree(ui->display, DefaultVisual(ui->display, DefaultScreen(ui->display)),
DefaultColormap(ui->display, DefaultScreen(ui->display)), &discol);
} }
if (displayprb[0] != '\0' && ui->prbfont) { {
const FcChar8 *text = (const FcChar8 *)displayprb;
int len = strlen((const char *)text);
XGlyphInfo extents; XGlyphInfo extents;
XftTextExtentsUtf8(ui->display, ui->prbfont, text, len, &extents); XftTextExtentsUtf8(ui->display, ui->problemLabel.font,
(const FcChar8 *)ui->problemLabel.text,
strlen(ui->problemLabel.text), &extents);
int tx = w - 20 - extents.xOff; int tx = w - 20 - extents.xOff;
int ty = 80;
XftColor discol; XftDrawStringUtf8(
XftColorAllocName(ui->display, backdraw, &ui->problemLabel.fg_color,
DefaultVisual(ui->display, DefaultScreen(ui->display)), ui->problemLabel.font, tx, ui->problemLabel.y,
DefaultColormap(ui->display, DefaultScreen(ui->display)), (const FcChar8 *)ui->problemLabel.text, 32);
"#b61729", &discol);
XftDrawStringUtf8(backdraw, &discol, ui->prbfont, tx, ty, text, len);
XftColorFree(ui->display,
DefaultVisual(ui->display, DefaultScreen(ui->display)),
DefaultColormap(ui->display, DefaultScreen(ui->display)), &discol);
} }
for (int i = 0; i < 64; ++i) ui->buttons[i] = NULL;
int width = 93; int width = 93;
int height = 60; int height = 60;
int padding = 2; int padding = 2;
printf("ウィンドウ: (%dx%d)\n", attr.width, attr.height); printf("ウィンドウ: (%dx%d)\n", attr.width, attr.height);
for (int row = 0; row < 6; ++row) { if (initialized == 0) {
XftColorAllocName(ui->display,
DefaultVisual(ui->display, DefaultScreen(ui->display)),
DefaultColormap(ui->display, DefaultScreen(ui->display)),
"#232020", &buttonColor);
}
initialized = 1;
for (int row = 1; row < NUM_ROWS; ++row) {
int y = 162 + row * (height + padding); int y = 162 + row * (height + padding);
if (y + height > h) break;
int cols = 4; for (int col = 0; col < NUM_COLS; ++col) {
for (int col = 0; col < cols; ++col) {
const char *label = btn_labels[row][col]; const char *label = btn_labels[row][col];
if (!label) continue; if (!label) continue;
int x = padding + col * (width + padding); int x = padding + col * (width + padding);
SuwaButton btn; SuwaButton *btn = malloc(sizeof(SuwaButton));
btn.x = x; btn->x = x;
btn.y = y; btn->y = y;
btn.width = width; btn->width = width;
btn.height = height; btn->height = height;
btn.label = label; btn->text = label;
btn.pressed = 0; btn->bg_color = BTCOL;
btn->fg_color = buttonColor;
btn->pressed = 0;
// ui->buttons[0] = btn;
drawbuttons(ui, &btn, backdraw); drawbuttons(ui, btn, backdraw);
} }
} }
XCopyArea(ui->display, ui->backbuf, ui->window, ui->gc, 0, 0, w, h, 0, 0); XCopyArea(ui->display, ui->backbuf, ui->xwindow, ui->gc, 0, 0, w, h, 0, 0);
XftDrawDestroy(backdraw); XftDrawDestroy(backdraw);
XFlush(ui->display); XFlush(ui->display);
} }
@@ -275,23 +272,26 @@ void handle_button_release(UiSystem *ui, int mx, int my) {
XftDrawDestroy(backdraw); XftDrawDestroy(backdraw);
XFlush(ui->display); XFlush(ui->display);
const char *label = btn->label; const char *label = btn->text;
if (strcmp(label, "C") == 0) { if (strcmp(label, "C") == 0) {
clear_calculator(); clear_calculator(ui);
} else if (strcmp(label, "<") == 0) { } else if (strcmp(label, "<") == 0) {
curinput[--input_pos] = '\0'; curinput[--input_pos] = '\0';
strcpy(displaytxt, curinput[0] ? curinput : "0"); strcpy(ui->resLabel.text, curinput[0] ? curinput : "0");
} else if (strcmp(label, "=") == 0) { } else if (strcmp(label, "=") == 0) {
double res = evaluate_simple(curinput); double res = evaluate_simple(ui, curinput);
if (isnan(res)) { if (isnan(res)) {
strncpy(displaytxt, "Error", 5); strncpy(ui->resLabel.text, "Error", 5);
} else { } else {
snprintf(displaytxt, sizeof(displaytxt), "%.8g", res); snprintf(ui->resLabel.text, sizeof(ui->resLabel.text), "%.8g", res);
strncpy(curinput, displaytxt, strlen(displaytxt)); strncpy(curinput, ui->resLabel.text, strlen(ui->resLabel.text));
input_pos = strlen(curinput); input_pos = strlen(curinput);
strcpy(curinput, "");
curinput[0] = '\0';
input_pos = 0;
} }
} else if (strlen(label) == 1) { } else if (strlen(label) == 1) {
append_to_input(label[0]); append_to_input(ui, label[0]);
} }
control_expose(ui, &(XEvent){.type = Expose}); control_expose(ui, &(XEvent){.type = Expose});
@@ -307,7 +307,7 @@ void handle_key_press(UiSystem *ui, XEvent *event) {
len = XLookupString(&event->xkey, buf, sizeof(buf), &keysym, NULL); len = XLookupString(&event->xkey, buf, sizeof(buf), &keysym, NULL);
if (keysym == XK_Q) { if (keysym == XK_Q) {
isrunning = 0; ui->isrunning = 0;
return; return;
} }
@@ -341,16 +341,16 @@ void handle_key_press(UiSystem *ui, XEvent *event) {
} }
if (keysym == XK_C) { if (keysym == XK_C) {
clear_calculator(); clear_calculator(ui);
goto redraw; goto redraw;
} }
if (keysym == XK_Return || keysym == XK_KP_Enter) { if (keysym == XK_Return || keysym == XK_KP_Enter) {
double res = evaluate_simple(curinput); double res = evaluate_simple(ui, curinput);
if (isnan(res)) { if (isnan(res)) {
strncpy(displaytxt, "Error", 5); strncpy(ui->resLabel.text, "Error", 5);
} else { } else {
snprintf(displaytxt, sizeof(displaytxt), "%.8g", res); snprintf(ui->resLabel.text, sizeof(ui->resLabel.text), "%.8g", res);
} }
goto redraw; goto redraw;
} }
@@ -359,7 +359,7 @@ void handle_key_press(UiSystem *ui, XEvent *event) {
|| (keysym == XK_Delete && input_pos > 0) || (keysym == XK_Delete && input_pos > 0)
|| (keysym == XK_X && input_pos > 0)) { || (keysym == XK_X && input_pos > 0)) {
curinput[--input_pos] = '\0'; curinput[--input_pos] = '\0';
strcpy(displaytxt, curinput[0] ? curinput : "0"); strcpy(ui->resLabel.text, curinput[0] ? curinput : "0");
goto redraw; goto redraw;
} }
@@ -373,7 +373,7 @@ void handle_key_press(UiSystem *ui, XEvent *event) {
else if (keysym == XK_KP_Decimal || keysym == XK_period) c = '.'; else if (keysym == XK_KP_Decimal || keysym == XK_period) c = '.';
if (c) { if (c) {
append_to_input(c); append_to_input(ui, c);
goto redraw; goto redraw;
} }

View File

@@ -1,17 +1,16 @@
#include "display.h" #include "display.h"
#include "program.h"
#include <string.h> #include <string.h>
void drawbuttons(UiSystem *ui, SuwaButton *btn, XftDraw *xftdraw) { void drawbuttons(UiSystem *ui, SuwaButton *btn, XftDraw *xftdraw) {
unsigned long curbg = btn->pressed ? BTSEL : BTCOL; unsigned long curbg = btn->pressed ? BTSEL : btn->bg_color;
XSetForeground(ui->display, ui->gc, curbg); XSetForeground(ui->display, ui->gc, curbg);
XFillRectangle(ui->display, ui->target, ui->gc, btn->x, btn->y, XFillRectangle(ui->display, ui->target, ui->gc, btn->x, btn->y,
btn->width, btn->height); btn->width, btn->height);
// 文字の中央に // 文字の中央に
if (btn->label && ui->font && xftdraw) { if (btn->text && ui->font && xftdraw) {
const FcChar8 *str = (const FcChar8 *)btn->label; const FcChar8 *str = (const FcChar8 *)btn->text;
int len = strlen((const char *)str); int len = strlen((const char *)str);
XGlyphInfo extents; XGlyphInfo extents;
@@ -23,9 +22,7 @@ void drawbuttons(UiSystem *ui, SuwaButton *btn, XftDraw *xftdraw) {
int tx = btn->x + (btn->width - text_w) / 2; int tx = btn->x + (btn->width - text_w) / 2;
int ty = btn->y + (btn->height - text_h) / 2 + ui->font->ascent; int ty = btn->y + (btn->height - text_h) / 2 + ui->font->ascent;
// tx -= extents.x;
XftDrawStringUtf8(xftdraw, &ui->color, ui->font, tx, ty, XftDrawStringUtf8(xftdraw, &ui->color, ui->font, tx, ty,
(FcChar8 *)btn->label, len); (FcChar8 *)btn->text, len);
} }
} }

View File

@@ -1,6 +1,5 @@
#pragma once #pragma once
#include "program.h"
#include "ui.h" #include "ui.h"
void drawbuttons(UiSystem *ui, SuwaButton *btn, XftDraw *xftdraw); void drawbuttons(UiSystem *ui, SuwaButton *btn, XftDraw *xftdraw);

View File

@@ -1,12 +0,0 @@
#include "program.h"
int window_width = 382;
int window_height = 534;
int isrunning = 1;
char displayprb[128] = "";
char curinput[256] = {0};
char displaytxt[64] = "0";
int input_pos = 0;
Pixmap backbuf = None;
SuwaButton *hovered_btn = NULL;
SuwaButton *pressed_btn = NULL;

View File

@@ -1,19 +0,0 @@
#pragma once
#include "ui.h"
#define FGCOL 0xfcfcfc
#define BGCOL 0x232020
#define BTSEL 0xb61729
#define BTCOL 0xee4030
#define BTHVR 0xf35869
extern int window_width;
extern int window_height;
extern int isrunning;
extern char displayprb[128];
extern char curinput[256];
extern char displaytxt[64];
extern int input_pos;
extern SuwaButton *hovered_btn;
extern SuwaButton *pressed_btn;

View File

@@ -3,21 +3,45 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xft/Xft.h> #include <X11/Xft/Xft.h>
typedef struct { #define FGCOL 0xfcfcfc
Display *display; #define BGCOL 0x232020
Window window; #define BTSEL 0xb61729
Drawable target; #define BTCOL 0xee4030
GC gc; #define BTHVR 0xf35869
Visual visual;
XftDraw *xftdraw;
XftColor color, btncolor, textcolor;
XftFont *font, *prbfont, *disfont;
Colormap colormap;
Pixmap backbuf;
} UiSystem;
typedef struct { typedef struct {
int x, y, width, height; int x, y, width, height;
const char *label; } SuwaWindow;
typedef struct {
int x, y, width, height;
const char *text;
XftFont *font;
int bg_color;
XftColor fg_color;
int pressed; // 0 = 普通、1 = 押している int pressed; // 0 = 普通、1 = 押している
} SuwaButton; } SuwaButton;
typedef struct {
int x, y, width, height;
char text[32];
XftFont *font;
XftColor fg_color;
} SuwaLabel;
typedef struct {
int isrunning;
Display *display;
Window xwindow;
Drawable target;
GC gc;
Visual visual;
XftColor color;
XftFont *font;
Colormap colormap;
Pixmap backbuf;
SuwaWindow window;
SuwaLabel resLabel;
SuwaLabel problemLabel;
SuwaButton *buttons[32];
} UiSystem;

View File

@@ -1,20 +1,17 @@
#include "utils.h" #include "utils.h"
void cleanup(UiSystem *ui) { void cleanup(UiSystem *ui) {
if (ui->textcolor.pixel != 0) // フォント
XftColorFree(ui->display, &ui->visual, ui->colormap, &ui->textcolor); if (ui->resLabel.font) XftFontClose(ui->display, ui->resLabel.font);
if (ui->btncolor.pixel != 0) if (ui->problemLabel.font) XftFontClose(ui->display, ui->problemLabel.font);
XftColorFree(ui->display, &ui->visual, ui->colormap, &ui->btncolor);
if (ui->color.pixel != 0)
XftColorFree(ui->display, &ui->visual, ui->colormap, &ui->color);
if (ui->disfont) XftFontClose(ui->display, ui->disfont);
if (ui->prbfont) XftFontClose(ui->display, ui->prbfont);
if (ui->font) XftFontClose(ui->display, ui->font); if (ui->font) XftFontClose(ui->display, ui->font);
// その他
if (ui->gc) XFreeGC(ui->display, ui->gc); if (ui->gc) XFreeGC(ui->display, ui->gc);
if (ui->backbuf) { if (ui->backbuf) {
XFreePixmap(ui->display, ui->backbuf); XFreePixmap(ui->display, ui->backbuf);
ui->backbuf = None; ui->backbuf = None;
} }
if (ui->window) XDestroyWindow(ui->display, ui->window); if (ui->xwindow) XDestroyWindow(ui->display, ui->xwindow);
if (ui->display) XCloseDisplay(ui->display); if (ui->display) XCloseDisplay(ui->display);
} }

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "program.h" #include "ui.h"
void cleanup(UiSystem *ui); void cleanup(UiSystem *ui);