最適化
This commit is contained in:
6
Makefile
6
Makefile
@@ -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}
|
||||||
|
|||||||
@@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
\
|
\
|
||||||
|
|||||||
119
main.c
119
main.c
@@ -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:
|
||||||
|
|||||||
152
src/control.c
152
src/control.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
@@ -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;
|
|
||||||
50
src/ui.h
50
src/ui.h
@@ -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;
|
||||||
|
|||||||
15
src/utils.c
15
src/utils.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "program.h"
|
#include "ui.h"
|
||||||
|
|
||||||
void cleanup(UiSystem *ui);
|
void cleanup(UiSystem *ui);
|
||||||
|
|||||||
Reference in New Issue
Block a user