summaryrefslogtreecommitdiff
path: root/src/minibuffer.c
blob: 762bbe7e0e4d02544479fca4e185500ba791215a (plain)
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
#include "minibuffer.h"
#include "buffer.h"
#include "display.h"

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

static struct minibuffer {
  struct buffer *buffer;
  struct timespec expires;
} g_minibuffer = {0};

struct margin update(struct buffer *buffer, struct command_list *commands,
                     uint32_t width, uint32_t height, uint64_t frame_time,
                     void *userdata) {
  struct timespec current;
  struct minibuffer *mb = (struct minibuffer *)userdata;
  clock_gettime(CLOCK_MONOTONIC, &current);
  if (current.tv_sec >= mb->expires.tv_sec) {
    buffer_clear(buffer);
  }

  return (struct margin){0};
}

void minibuffer_init(struct buffer *buffer) {
  g_minibuffer.buffer = buffer;
  buffer_add_update_hook(g_minibuffer.buffer, update, &g_minibuffer);
}

void echo(uint32_t timeout, const char *fmt, va_list args) {
  char buff[2048];
  size_t nbytes = vsnprintf(buff, 2048, fmt, args);

  // vsnprintf returns how many characters it would have wanted to write in case
  // of overflow
  buffer_clear(g_minibuffer.buffer);
  buffer_add_text(g_minibuffer.buffer, (uint8_t *)buff,
                  nbytes > 2048 ? 2048 : nbytes);

  clock_gettime(CLOCK_MONOTONIC, &g_minibuffer.expires);
  g_minibuffer.expires.tv_sec += timeout;
}

void minibuffer_echo(const char *fmt, ...) {
  va_list args;
  va_start(args, fmt);
  echo(1000, fmt, args);
  va_end(args);
}

void minibuffer_echo_timeout(uint32_t timeout, const char *fmt, ...) {
  va_list args;
  va_start(args, fmt);
  echo(timeout, fmt, args);
  va_end(args);
}

bool minibuffer_displaying() { return !buffer_is_empty(g_minibuffer.buffer); }
void minibuffer_clear() { g_minibuffer.expires.tv_nsec = 0; }