forked from micropython/micropython
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathTerminal.c
176 lines (155 loc) · 6.37 KB
/
Terminal.c
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include <stdint.h>
#include "shared-bindings/terminalio/Terminal.h"
#include "shared-bindings/util.h"
#include "py/stream.h"
#include "py/objproperty.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "shared-bindings/fontio/BuiltinFont.h"
#if CIRCUITPY_LVFONTIO
#include "shared-bindings/lvfontio/OnDiskFont.h"
#endif
//| class Terminal:
//| """Display a character stream with a TileGrid
//|
//| ASCII control:
//| * ``\\r`` - Move cursor to column 1
//| * ``\\n`` - Move cursor down a row
//| * ``\\b`` - Move cursor left one if possible
//|
//| OSC control sequences:
//| * ``ESC ] 0; <s> ESC \\`` - Set title bar to <s>
//| * ``ESC ] ####; <s> ESC \\`` - Ignored
//|
//| VT100 control sequences:
//| * ``ESC [ K`` - Clear the remainder of the line
//| * ``ESC [ 0 K`` - Clear the remainder of the line
//| * ``ESC [ 1 K`` - Clear start of the line to cursor
//| * ``ESC [ 2 K`` - Clear the entire line
//| * ``ESC [ #### D`` - Move the cursor to the left by ####
//| * ``ESC [ 2 J`` - Erase the entire display
//| * ``ESC [ nnnn ; mmmm H`` - Move the cursor to mmmm, nnnn.
//| * ``ESC [ H`` - Move the cursor to 0,0.
//| * ``ESC M`` - Move the cursor up one line, scrolling if necessary.
//| * ``ESC D`` - Move the cursor down one line, scrolling if necessary.
//| * ``ESC [ r`` - Disable scrolling range (set to fullscreen).
//| * ``ESC [ nnnn ; mmmm r`` - Set scrolling range between rows nnnn and mmmm.
//| * ``ESC [ ## m`` - Set the terminal display attributes.
//| * ``ESC [ ## ; ## m`` - Set the terminal display attributes.
//| * ``ESC [ ## ; ## ; ## m`` - Set the terminal display attributes.
//|
//| Supported Display attributes:
//| 0 - Reset all attributes
//| Foreground Colors Background Colors
//| 30 - Black 40 - Black
//| 31 - Red 41 - Red
//| 32 - Green 42 - Green
//| 33 - Yellow 43 - Yellow
//| 34 - Blue 44 - Blue
//| 35 - Magenta 45 - Magenta
//| 36 - Cyan 46 - Cyan
//| 37 - White 47 - White
//| """
//|
//| def __init__(
//| self,
//| scroll_area: displayio.TileGrid,
//| font: fontio.BuiltinFont,
//| *,
//| status_bar: Optional[displayio.TileGrid] = None,
//| ) -> None:
//| """Terminal manages tile indices and cursor position based on VT100 commands. The font should be
//| a `fontio.BuiltinFont` and the TileGrid's bitmap should match the font's bitmap."""
//| ...
//|
static mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_scroll_area, ARG_font, ARG_status_bar };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_scroll_area, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_font, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_status_bar, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
displayio_tilegrid_t *scroll_area = mp_arg_validate_type(args[ARG_scroll_area].u_obj, &displayio_tilegrid_type, MP_QSTR_scroll_area);
displayio_tilegrid_t *status_bar = NULL;
if (args[ARG_status_bar].u_obj != mp_const_none) {
status_bar = mp_arg_validate_type(args[ARG_status_bar].u_obj, &displayio_tilegrid_type, MP_QSTR_status_bar);
}
mp_obj_t font = args[ARG_font].u_obj;
// Ensure the font is one of the supported types
bool valid_font = false;
#if CIRCUITPY_FONTIO
if (mp_obj_is_type(font, &fontio_builtinfont_type)) {
valid_font = true;
}
#endif
#if CIRCUITPY_LVFONTIO
if (mp_obj_is_type(font, &lvfontio_ondiskfont_type)) {
valid_font = true;
}
#endif
if (!valid_font) {
mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_font);
}
mp_arg_validate_int_min(scroll_area->width_in_tiles * scroll_area->height_in_tiles, 2, MP_QSTR_scroll_area_area);
terminalio_terminal_obj_t *self = mp_obj_malloc(terminalio_terminal_obj_t, &terminalio_terminal_type);
common_hal_terminalio_terminal_construct(self, scroll_area, font, status_bar);
return MP_OBJ_FROM_PTR(self);
}
// These are standard stream methods. Code is in py/stream.c.
//
//| def write(self, buf: ReadableBuffer) -> Optional[int]:
//| """Write the buffer of bytes to the bus.
//|
//| :return: the number of bytes written
//| :rtype: int or None"""
//| ...
//|
//|
static mp_uint_t terminalio_terminal_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in);
const byte *buf = buf_in;
return common_hal_terminalio_terminal_write(self, buf, size, errcode);
}
static mp_uint_t terminalio_terminal_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_uint_t ret;
if (request == MP_STREAM_POLL) {
mp_uint_t flags = arg;
ret = 0;
if ((flags & MP_STREAM_POLL_WR) && common_hal_terminalio_terminal_ready_to_tx(self)) {
ret |= MP_STREAM_POLL_WR;
}
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
}
return ret;
}
static const mp_rom_map_elem_t terminalio_terminal_locals_dict_table[] = {
// Standard stream methods.
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
};
static MP_DEFINE_CONST_DICT(terminalio_terminal_locals_dict, terminalio_terminal_locals_dict_table);
static const mp_stream_p_t terminalio_terminal_stream_p = {
.read = NULL,
.write = terminalio_terminal_write,
.ioctl = terminalio_terminal_ioctl,
.is_text = true,
};
MP_DEFINE_CONST_OBJ_TYPE(
terminalio_terminal_type,
MP_QSTR_Terminal,
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
make_new, terminalio_terminal_make_new,
locals_dict, (mp_obj_dict_t *)&terminalio_terminal_locals_dict,
iter, mp_stream_unbuffered_iter,
protocol, &terminalio_terminal_stream_p
);