|
0
|
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 } |