summaryrefslogtreecommitdiff
path: root/src/user/popups/info.c
blob: 667d4405f7abc554a53d871dc821a6e9502f504a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <popups/popup.h>

#include <libfont/fonts.h>

#include <knob/format.h>
#include <knob/heap.h>

#include <stdint.h>
#include <stdarg.h>

#define PADDING 6
#define FONT "fixed-10"

static const struct font_info *info_font = 0;

static const struct key_packet info_quits[] = {
  { .key_id = KEY_ESCAPE, .modifiers = NO_MODS },
  { .key_id = 0 }
};

void info_popup(struct popup *into, const char *msg, uint8_t fg, uint8_t bg) {
  if (!info_font)
    info_font = get_font(FONT);

  uint32_t w = 0, h = 1, lw = 0;
  for (const char *i = msg; *i; ++i)
    if (*i == '\n') {
      ++h;
      if (lw > w)
        w = lw;
      lw = 0;
    }
    else
      ++lw;
  if (lw > w)
    w = lw;

  into->has_quit = false;
  into->quit_binds = (struct key_packet *)info_quits;

  const uint32_t pitch  = info_font->space_width  * w + 2 * PADDING;
  const uint32_t height = info_font->space_height * h + 2 * PADDING;

  uint8_t *const pixbuf = get_block(pitch * height);

  for (uint32_t y = 0; y < height; ++y)
    for (uint32_t x = 0; x < pitch; ++x)
      pixbuf[y * pitch + x] = bg;

  uint32_t my = 0;
  uint32_t mx = 0;
  --msg;
  while (*++msg) {
    if (*msg == '\n') {
      ++my;
      mx = 0;
    }
    else
      put_char(info_font, *msg, pixbuf + (my * info_font->space_height + PADDING) * pitch + mx++ * info_font->space_width + PADDING, pitch, bg, fg);
  }

  into->pixbuf = pixbuf;
  into->handle = _new_window(pitch, height, pixbuf);
}

void info_popupf_v(struct popup *into, const char *text, uint8_t fg, uint8_t bg, va_list args) {
  char *const msg = format_v(text, args);
  info_popup(into, msg, fg, bg);
  free_block(msg);
}

void info_popupf(struct popup *into, const char *text, uint8_t fg, uint8_t bg, ...) {
  va_list args;
  va_start(args, bg);
  info_popupf_v(into, text, fg, bg, args);
  va_end(args);
}