comparison main.cpp @ 0:12567e0a7670 default tip

initial commit
author Yasuri <yasuri@charliesmp.net>
date Sun, 04 Oct 2026 12:56:43 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:12567e0a7670
1 #include <iostream>
2 #include <stdexcept>
3 #include <vector>
4 #include <string>
5 #include <sstream>
6 #include <cstring>
7 #include <unistd.h>
8 #include <X11/Xlib.h>
9 #include <X11/Xft/Xft.h>
10 #include <fontconfig/fontconfig.h>
11 #include <X11/keysym.h>
12 #include "calculate.h"
13 #include "x11.h"
14
15 extern "C" {
16 #include "drw.h"
17 }
18 #include "config.h"
19
20 struct Button { int x, y, w, h; std::string label; };
21
22 std::vector<Button> makeButtons() {
23 std::vector<Button> b;
24 for (int r = 0; r < 4; r++)
25 for (int c = 0; c < 4; c++)
26 b.push_back({gridX + c*(btnW+gap), gridY+ r*(btnH+gap), btnW, btnH, labels[r][c]});
27 return b;
28 }
29
30 void redraw(Drw* drw, Clr* btnScheme, Clr* dispScheme,
31 const std::vector<Button>& btns, const std::string& input) {
32 // display area (also paints the pixmap's background)
33 drw_setscheme(drw, dispScheme);
34 drw_rect(drw, 0, 0, 500, 500, 1, 1);
35 drw_text(drw, 10, 10, 480, 70, 10, input.c_str(), 0);
36
37 // buttons
38 drw_setscheme(drw, btnScheme);
39 for (const auto& b : btns) {
40 unsigned int tw = drw_fontset_getwidth(drw, b.label.c_str());
41 int lpad = (b.w - (int)tw) / 2;
42 drw_text(drw, b.x, b.y, b.w, b.h, lpad, b.label.c_str(), 0);
43 }
44 }
45
46 int main() {
47 Display *dpy = displayopen();
48 int screen = DefaultScreen(dpy);
49 Window root = RootWindow(dpy, screen);
50 Window win = XCreateSimpleWindow(dpy, root, 0, 0, 500, 500, 1, 0xFFFFFF, 0x000000);
51 XStoreName(dpy, win, "Calculator");
52 XSelectInput(dpy, win, ExposureMask | KeyPressMask | ButtonPressMask);
53 XMapWindow(dpy, win);
54
55 Atom wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
56 XSetWMProtocols(dpy, win, &wmDelete, 1);
57
58 Drw* drw = drw_create(dpy, screen, root, 500, 500);
59 if (!drw) { std::cerr << "drw_create failed\n"; return 1; }
60
61 if (!drw_fontset_create(drw, fonts, 1)) {
62 std::cerr << "font load failed\n";
63 return 1;
64 }
65
66 Clr* btnScheme = drw_scm_create(drw, btnColors, 3);
67 Clr* dispScheme = drw_scm_create(drw, dispColors, 3);
68
69 std::vector<Button> btns = makeButtons();
70 std::string input;
71 XEvent ev;
72 bool running = true;
73
74 while (running) {
75 XNextEvent(dpy, &ev);
76 switch (ev.type) {
77 case ClientMessage:
78 if ((Atom)ev.xclient.data.l[0] == wmDelete) running = false;
79 break;
80 case Expose:
81 if (ev.xexpose.count == 0) {
82 redraw(drw, btnScheme, dispScheme, btns, input);
83 drw_map(drw, win, 0, 0, winW, winH);
84 }
85 break;
86 case KeyPress: {
87 KeySym k = XLookupKeysym(&ev.xkey, 0);
88 if (k == XK_q) running = false;
89 break;
90 }
91 case ButtonPress:
92 if (ev.xbutton.button != Button1) break;
93 for (const auto& b : btns) {
94 bool hit = ev.xbutton.x >= b.x && ev.xbutton.x < b.x + b.w &&
95 ev.xbutton.y >= b.y && ev.xbutton.y < b.y + b.h;
96 if (!hit) continue;
97
98 if (b.label == "=") {
99 size_t pos = input.find_first_of("+-*/", 1);
100 if (pos != std::string::npos) {
101 try {
102 double x = std::stod(input.substr(0, pos));
103 double y = std::stod(input.substr(pos + 1));
104 char op = input[pos];
105 std::ostringstream ss;
106 ss << calculate(x, y, op);
107 input = ss.str();
108 } catch (const std::exception& e) {
109 input = e.what();
110 }
111 }
112 } else if (b.label == "C") {
113 input.clear();
114 } else {
115 input += b.label;
116 }
117 XClearArea(dpy, win, 0, 0, 0, 0, True);
118 break;
119 }
120 break;
121 }
122 }
123
124 drw_free(drw);
125 XCloseDisplay(dpy);
126 }