summaryrefslogtreecommitdiff
path: root/src/user/terminal/readline.c
blob: 37ef54b5f7100e9568ae3d13e0dd4252cbbec226 (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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <terminal/terminal.h>

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

#include <pland/syscall.h>

#include <stdint.h>

//returns length of string without null terminator
//max_length doesn't include null terminator
uint32_t read_line(char *sz, uint32_t max_length, const char *prompt) {
  uint32_t i = 0;
  uint32_t l = 0;

  term_add_sz_no_ww(prompt);
  paint_term();

  const _window_handle_t handle = active_term->window;
  struct window_action action;
  while (1) {
    _get_win_action(handle, &action);
    switch (action.action_type) {
    case NOT_READY:
      _wait_for_action();
      _yield_task();
      continue;
    case KEY_DOWN:
   //;char *const debug_msg = format("got key 0x%2x, 0x%3x", action.as_key.key_id, action.as_key.modifiers);
   // _system_log(debug_msg);
   // free_block(debug_msg);
      switch (action.as_key.key_id) {
      case KEY_DELETE:
        if (i != l) {
          cursor_right();
          ++i;
        }
      case KEY_BSPACE:
        if (!i)
          continue;
        --l;
        --i;
        for (uint8_t j = i; j < l; ++j)
          sz[j] = sz[j + 1];
        sz[l] = '\0';
        cursor_left();
        uint32_t cursor_backup_x = active_term->cursor_x;
        uint32_t cursor_backup_y = active_term->cursor_y;
        term_add_sz_no_ww(sz + i);
        term_add_char(' ');
        move_cursor(cursor_backup_y, cursor_backup_x);
        paint_term();
        continue;
      case KEY_ENTER:
        term_newline();
        paint_term();
        sz[l] = '\0';
        return l;
      case KEY_HOME:
      case KEY_UP_ARROW:
        for (; i; --i)
          cursor_left();
        paint_term();
        continue;
      case KEY_END:
      case KEY_DOWN_ARROW:
        for (; i != l; ++i)
          cursor_right();
        paint_term();
        continue;
      case KEY_LEFT_ARROW:
        if (i) {
          cursor_left();
          paint_term();
          --i;
        }
        continue;
      case KEY_RIGHT_ARROW:
        if (i != l) {
          cursor_right();
          paint_term();
          ++i;
        }
        continue;
      default:
        if (i == max_length)
          continue;
        char ch = key_to_char(action.as_key);
        if (ch) {
          term_add_char(ch);
          paint_term();
          sz[i] = ch;
          if (i == l)
            ++l;
          ++i;
        }
        continue;
      }
    default:
      continue;
    }
  }
}