view main.cpp @ 0:12567e0a7670 default tip

initial commit
author Yasuri <yasuri@charliesmp.net>
date Sun, 04 Oct 2026 12:56:43 -0500
parents
children
line wrap: on
line source

#include <iostream>
#include <stdexcept>
#include <vector>
#include <string>
#include <sstream>
#include <cstring>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
#include <fontconfig/fontconfig.h>
#include <X11/keysym.h>
#include "calculate.h"
#include "x11.h"

extern "C" {
#include "drw.h"
}
#include "config.h"

struct Button { int x, y, w, h; std::string label; };

std::vector<Button> makeButtons() {
  std::vector<Button> b;
  for (int r = 0; r < 4; r++)
    for (int c = 0; c < 4; c++)
      b.push_back({gridX + c*(btnW+gap), gridY+ r*(btnH+gap), btnW, btnH, labels[r][c]});
  return b;
}

void redraw(Drw* drw, Clr* btnScheme, Clr* dispScheme,
    const std::vector<Button>& btns, const std::string& input) {
  // display area (also paints the pixmap's background)
  drw_setscheme(drw, dispScheme);
  drw_rect(drw, 0, 0, 500, 500, 1, 1);
  drw_text(drw, 10, 10, 480, 70, 10, input.c_str(), 0);

  // buttons
  drw_setscheme(drw, btnScheme);
  for (const auto& b : btns) {
    unsigned int tw = drw_fontset_getwidth(drw, b.label.c_str());
    int lpad = (b.w - (int)tw) / 2;
    drw_text(drw, b.x, b.y, b.w, b.h, lpad, b.label.c_str(), 0);
  }
}

int main() {
  Display *dpy = displayopen();
  int screen = DefaultScreen(dpy);
  Window root = RootWindow(dpy, screen);
  Window win = XCreateSimpleWindow(dpy, root, 0, 0, 500, 500, 1, 0xFFFFFF, 0x000000);
  XStoreName(dpy, win, "Calculator");
  XSelectInput(dpy, win, ExposureMask | KeyPressMask | ButtonPressMask);
  XMapWindow(dpy, win);

  Atom wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  XSetWMProtocols(dpy, win, &wmDelete, 1);

  Drw* drw = drw_create(dpy, screen, root, 500, 500);
  if (!drw) { std::cerr << "drw_create failed\n"; return 1; }

  if (!drw_fontset_create(drw, fonts, 1)) {
    std::cerr << "font load failed\n";
    return 1;
  }

  Clr* btnScheme  = drw_scm_create(drw, btnColors, 3);
  Clr* dispScheme = drw_scm_create(drw, dispColors, 3);

  std::vector<Button> btns = makeButtons();
  std::string input;
  XEvent ev;
  bool running = true;

  while (running) {
    XNextEvent(dpy, &ev);
    switch (ev.type) {
      case ClientMessage:
        if ((Atom)ev.xclient.data.l[0] == wmDelete) running = false;
        break;
      case Expose:
        if (ev.xexpose.count == 0) {
          redraw(drw, btnScheme, dispScheme, btns, input);
          drw_map(drw, win, 0, 0, winW, winH);
        }
        break;
      case KeyPress: {
                       KeySym k = XLookupKeysym(&ev.xkey, 0);
                       if (k == XK_q) running = false;
                       break;
                     }
      case ButtonPress:
                     if (ev.xbutton.button != Button1) break;
                     for (const auto& b : btns) {
                       bool hit = ev.xbutton.x >= b.x && ev.xbutton.x < b.x + b.w &&
                         ev.xbutton.y >= b.y && ev.xbutton.y < b.y + b.h;
                       if (!hit) continue;

                       if (b.label == "=") {
                         size_t pos = input.find_first_of("+-*/", 1);
                         if (pos != std::string::npos) {
                           try {
                             double x = std::stod(input.substr(0, pos));
                             double y = std::stod(input.substr(pos + 1));
                             char op = input[pos];
                             std::ostringstream ss;
                             ss << calculate(x, y, op);
                             input = ss.str();
                           } catch (const std::exception& e) {
                             input = e.what();
                           }
                         }
                       } else if (b.label == "C") {
                         input.clear();
                       } else {
                         input += b.label;
                       }
                       XClearArea(dpy, win, 0, 0, 0, 0, True);
                       break;
                     }
                     break;
    }
  }

  drw_free(drw);
  XCloseDisplay(dpy);
}