text_editor: add viewport scrolling
This commit is contained in:
parent
487289f3c9
commit
cf4b078d0a
@ -91,6 +91,7 @@ namespace ft6 {
|
||||
}
|
||||
namespace ft6 {
|
||||
namespace scan_code {
|
||||
constexpr uint32_t first_printable = 0x4;
|
||||
constexpr uint32_t last_printable = 0x38;
|
||||
|
||||
const uint8_t code_point[last_printable + 1][2] = {
|
||||
@ -154,4 +155,3 @@ namespace ft6 {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ void gap_cursor_pos_abs(struct gap_buffer& gb, int32_t pos)
|
||||
gap_cursor_pos(gb, pos - gb.gap_start);
|
||||
}
|
||||
|
||||
int32_t gap_column_number(struct gap_buffer& gb)
|
||||
int32_t gap_column_number(const struct gap_buffer& gb)
|
||||
{
|
||||
int32_t line_start = 0;
|
||||
if (gb.line.gap > 0)
|
||||
|
@ -32,5 +32,5 @@ void gap_resize(struct gap_buffer& gb);
|
||||
void gap_append(struct gap_buffer& gb, char_type c);
|
||||
void gap_pop(struct gap_buffer& gb);
|
||||
void gap_cursor_pos(struct gap_buffer& gb, int32_t delta);
|
||||
int32_t gap_column_number(struct gap_buffer& gb);
|
||||
int32_t gap_column_number(const struct gap_buffer& gb);
|
||||
void gap_cursor_pos_line(struct gap_buffer& gb, int32_t delta);
|
||||
|
@ -119,14 +119,36 @@ void keyboard_debug(ft6::data_transfer::data_format * keyboards, uint32_t frame_
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_shifted(const uint8_t modifier_key)
|
||||
constexpr inline bool is_modified(uint32_t modifier, uint32_t bit)
|
||||
{
|
||||
return
|
||||
(ft6::data_transfer::modifier_key::right_shift() & modifier_key) ||
|
||||
(ft6::data_transfer::modifier_key::left_shift() & modifier_key);
|
||||
uint32_t mask = ~(bit);
|
||||
return ((modifier & bit) != 0) && ((modifier & mask) == 0);
|
||||
}
|
||||
|
||||
void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb)
|
||||
constexpr inline bool is_unmodified(uint32_t modifier)
|
||||
{
|
||||
return modifier == 0;
|
||||
}
|
||||
|
||||
constexpr inline bool is_shifted(uint32_t modifier)
|
||||
{
|
||||
uint32_t bit = ft6::data_transfer::modifier_key::right_shift() | ft6::data_transfer::modifier_key::left_shift();
|
||||
return is_modified(modifier, bit);
|
||||
}
|
||||
|
||||
constexpr inline bool is_left_alted(uint32_t modifier)
|
||||
{
|
||||
uint32_t bit = (ft6::data_transfer::modifier_key::left_alt());
|
||||
return is_modified(modifier, bit);
|
||||
}
|
||||
|
||||
constexpr inline bool is_ctrled(uint32_t modifier)
|
||||
{
|
||||
uint32_t bit = (ft6::data_transfer::modifier_key::left_control() | ft6::data_transfer::modifier_key::right_control());
|
||||
return is_modified(modifier, bit);
|
||||
}
|
||||
|
||||
void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb, viewport_window& vw)
|
||||
{
|
||||
uint32_t this_frame = (frame_ix + 0) & 1;
|
||||
uint32_t next_frame = (frame_ix + 1) & 1;
|
||||
@ -144,15 +166,21 @@ void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame
|
||||
}
|
||||
if (make) {
|
||||
// make
|
||||
int modifier_key = keyboards[this_frame].modifier_key;
|
||||
uint8_t scan_code = keyboards[this_frame].scan_code_array[i];
|
||||
if (scan_code <= ft6::scan_code::last_printable) {
|
||||
bool shifted = is_shifted(keyboards[this_frame].modifier_key);
|
||||
|
||||
if (is_shifted(modifier_key) || is_unmodified(modifier_key)) {
|
||||
if (scan_code >= ft6::scan_code::first_printable && scan_code <= ft6::scan_code::last_printable) {
|
||||
bool shifted = is_shifted(modifier_key);
|
||||
char_type code_point = ft6::scan_code::code_point[scan_code][shifted];
|
||||
if (code_point != 0) {
|
||||
gap_append(gb, code_point);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_unmodified(modifier_key)) {
|
||||
switch (scan_code) {
|
||||
case ft6::scan_code::_return: gap_append(gb, '\n'); break;
|
||||
case ft6::scan_code::backspace: gap_pop(gb); break;
|
||||
@ -162,8 +190,32 @@ void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame
|
||||
case ft6::scan_code::right_arrow: gap_cursor_pos(gb, 1); break;
|
||||
case ft6::scan_code::up_arrow: gap_cursor_pos_line(gb, -1); break;
|
||||
case ft6::scan_code::down_arrow: gap_cursor_pos_line(gb, 1); break;
|
||||
default:
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_left_alted(modifier_key)) {
|
||||
switch (scan_code) {
|
||||
case ft6::scan_code::v_V:
|
||||
vw.first_line -= 1;
|
||||
if (vw.first_line < 0)
|
||||
vw.first_line = 0;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ctrled(modifier_key)) {
|
||||
switch (scan_code) {
|
||||
case ft6::scan_code::v_V:
|
||||
vw.first_line += 1;
|
||||
if ((vw.first_line - 1) >= gb.line.length) {
|
||||
vw.first_line = gb.line.length;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,10 @@
|
||||
|
||||
#include "maple/maple_bus_ft6.hpp"
|
||||
#include "gap_buffer.hpp"
|
||||
#include "viewport_window.hpp"
|
||||
|
||||
void keyboard_do_get_condition(ft6::data_transfer::data_format& data);
|
||||
|
||||
void keyboard_debug(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix);
|
||||
|
||||
void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb);
|
||||
void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb, viewport_window& vw);
|
||||
|
70
text_editor/parse.cpp
Normal file
70
text_editor/parse.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "parse.hpp"
|
||||
|
||||
int parse_base10_digit(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case '0': return 0;
|
||||
case '1': return 1;
|
||||
case '2': return 2;
|
||||
case '3': return 3;
|
||||
case '4': return 4;
|
||||
case '5': return 5;
|
||||
case '6': return 6;
|
||||
case '7': return 7;
|
||||
case '8': return 8;
|
||||
case '9': return 9;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char * parse_base10(const char * s, int * n)
|
||||
{
|
||||
*n = 0;
|
||||
int sign = 1;
|
||||
|
||||
if (*s == '-') {
|
||||
sign = -1;
|
||||
s++;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int digit = parse_base10_digit(*s);
|
||||
if (digit == -1)
|
||||
break;
|
||||
|
||||
*n *= 10;
|
||||
*n += digit;
|
||||
s++;
|
||||
}
|
||||
|
||||
*n *= sign;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
const char * parse_base10_64(const char * s, int64_t * n)
|
||||
{
|
||||
*n = 0;
|
||||
int sign = 1;
|
||||
|
||||
if (*s == '-') {
|
||||
sign = -1;
|
||||
s++;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int digit = parse_base10_digit(*s);
|
||||
if (digit == -1)
|
||||
break;
|
||||
|
||||
*n *= 10;
|
||||
*n += digit;
|
||||
s++;
|
||||
}
|
||||
|
||||
*n *= sign;
|
||||
|
||||
return s;
|
||||
}
|
5
text_editor/parse.hpp
Normal file
5
text_editor/parse.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include <stddef.h>
|
||||
|
||||
int parse_base10_digit(char c);
|
||||
const char * parse_base10(const char * s, int * n);
|
||||
const char * parse_base10_64(const char * s, int64_t * n);
|
173
text_editor/printf.cpp
Normal file
173
text_editor/printf.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "parse.hpp"
|
||||
#include "unparse.hpp"
|
||||
#include "printf.hpp"
|
||||
|
||||
enum format_type {
|
||||
FORMAT_BASE10_UNSIGNED,
|
||||
FORMAT_BASE10,
|
||||
FORMAT_BASE10_64,
|
||||
FORMAT_POINTER,
|
||||
FORMAT_BASE16,
|
||||
FORMAT_STRING,
|
||||
FORMAT_CHAR,
|
||||
FORMAT_PERCENT,
|
||||
};
|
||||
|
||||
struct format {
|
||||
enum format_type type;
|
||||
int pad_length;
|
||||
char fill_char;
|
||||
};
|
||||
|
||||
static const char * parse_escape(const char * format, struct format * ft);
|
||||
|
||||
static const char * parse_fill_pad(const char * format, struct format * ft)
|
||||
{
|
||||
if (*format == 0)
|
||||
return format;
|
||||
if (*format >= '1' || *format <= '9')
|
||||
ft->fill_char = ' ';
|
||||
else
|
||||
ft->fill_char = *format++;
|
||||
format = parse_base10(format, &ft->pad_length);
|
||||
return parse_escape(format, ft);
|
||||
}
|
||||
|
||||
static const char * parse_escape(const char * format, struct format * ft)
|
||||
{
|
||||
switch (*format) {
|
||||
case 0:
|
||||
return format;
|
||||
case 'u':
|
||||
ft->type = FORMAT_BASE10_UNSIGNED;
|
||||
return format + 1;
|
||||
case 'd':
|
||||
ft->type = FORMAT_BASE10;
|
||||
return format + 1;
|
||||
case 'l':
|
||||
ft->type = FORMAT_BASE10_64;
|
||||
return format + 1;
|
||||
case 'p':
|
||||
ft->type = FORMAT_POINTER;
|
||||
return format + 1;
|
||||
case 'x':
|
||||
ft->type = FORMAT_BASE16;
|
||||
return format + 1;
|
||||
case 's':
|
||||
ft->type = FORMAT_STRING;
|
||||
return format + 1;
|
||||
case 'c':
|
||||
ft->type = FORMAT_CHAR;
|
||||
return format + 1;
|
||||
case '%':
|
||||
ft->type = FORMAT_PERCENT;
|
||||
return format + 1;
|
||||
default:
|
||||
return parse_fill_pad(format, ft);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int copy_string(const char * src, int src_len, char * dst, int dst_len, int dst_ix)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < src_len; i++) {
|
||||
if (dst_ix + i >= dst_len)
|
||||
break;
|
||||
dst[dst_ix + i] = src[i];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int snprintf(char * buf, int buf_len, const char * format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
int buf_ix = 0;
|
||||
|
||||
while (buf_ix < buf_len) {
|
||||
if (*format == 0)
|
||||
break;
|
||||
|
||||
switch (*format) {
|
||||
case '%':
|
||||
{
|
||||
struct format ft;
|
||||
ft.pad_length = 0;
|
||||
ft.fill_char = 0;
|
||||
format = parse_escape(format + 1, &ft);
|
||||
switch (ft.type) {
|
||||
case FORMAT_BASE10_UNSIGNED:
|
||||
{
|
||||
uint32_t num = va_arg(args, uint32_t);
|
||||
char s[10];
|
||||
int offset = unparse_base10_unsigned(s, num, ft.pad_length, ft.fill_char);
|
||||
buf_ix += copy_string(s, offset, buf, buf_len, buf_ix);
|
||||
}
|
||||
break;
|
||||
case FORMAT_BASE10:
|
||||
{
|
||||
int32_t num = va_arg(args, int32_t);
|
||||
char s[10];
|
||||
int offset = unparse_base10(s, num, ft.pad_length, ft.fill_char);
|
||||
buf_ix += copy_string(s, offset, buf, buf_len, buf_ix);
|
||||
}
|
||||
break;
|
||||
case FORMAT_BASE10_64:
|
||||
{
|
||||
int64_t num = va_arg(args, int64_t);
|
||||
char s[20];
|
||||
int offset = unparse_base10_64(s, num, ft.pad_length, ft.fill_char);
|
||||
buf_ix += copy_string(s, offset, buf, buf_len, buf_ix);
|
||||
}
|
||||
break;
|
||||
case FORMAT_POINTER:
|
||||
{
|
||||
const char s[2] = {'0', 'x'};
|
||||
buf_ix += copy_string(s, 2, buf, buf_len, buf_ix);
|
||||
}
|
||||
/* fall through */;
|
||||
case FORMAT_BASE16:
|
||||
{
|
||||
uint32_t num = va_arg(args, uint32_t);
|
||||
char s[8];
|
||||
int offset = unparse_base16(s, num, ft.pad_length, ft.fill_char);
|
||||
buf_ix += copy_string(s, offset, buf, buf_len, buf_ix);
|
||||
}
|
||||
break;
|
||||
case FORMAT_STRING:
|
||||
{
|
||||
const char * s = va_arg(args, const char *);
|
||||
while (*s != 0 && buf_ix < buf_len) {
|
||||
buf[buf_ix++] = *s++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FORMAT_CHAR:
|
||||
{
|
||||
const int c = va_arg(args, const int);
|
||||
buf[buf_ix++] = c;
|
||||
}
|
||||
break;
|
||||
case FORMAT_PERCENT:
|
||||
buf[buf_ix++] = '%';
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
char c = *format++;
|
||||
buf[buf_ix++] = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return buf_ix;
|
||||
}
|
3
text_editor/printf.hpp
Normal file
3
text_editor/printf.hpp
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
int snprintf(char * buf, int len, const char * format, ...);
|
@ -1,6 +1,7 @@
|
||||
#include "render.hpp"
|
||||
#include "minmax.hpp"
|
||||
#include "transform.hpp"
|
||||
#include "unparse.hpp"
|
||||
|
||||
#include "holly/ta_global_parameter.hpp"
|
||||
#include "holly/ta_fifo_polygon_converter.hpp"
|
||||
@ -36,9 +37,11 @@ cursor_advance render_primary_buffer(ta_parameter_writer& writer,
|
||||
const gap_buffer& gb,
|
||||
const viewport_window& window)
|
||||
{
|
||||
int32_t first_line = min(window.first_line, gb.line.length - 1);
|
||||
int32_t first_line = window.first_line;
|
||||
|
||||
cursor_advance cursor = { 0 };
|
||||
cursor.x = -1;
|
||||
cursor.y = -1;
|
||||
int32_t h_advance = 0;
|
||||
int32_t v_advance = 0;
|
||||
|
||||
@ -47,7 +50,16 @@ cursor_advance render_primary_buffer(ta_parameter_writer& writer,
|
||||
|
||||
int row = first_line;
|
||||
|
||||
int32_t init_i = first_line >= 0 ? gb.line.offsets[first_line] + 1 : 0;
|
||||
// line 0 is prior to the beginning of gb.line.offsets
|
||||
// gb.line.offsets is the index of the newline character
|
||||
int32_t init_i;
|
||||
if (first_line == 0) {
|
||||
init_i = 0;
|
||||
} else if ((first_line - 1) >= 0 && (first_line - 1) < gb.line.length) {
|
||||
init_i = gb.line.offsets[first_line - 1] + 1;
|
||||
} else {
|
||||
init_i = gb.size;
|
||||
}
|
||||
for (int32_t i = init_i; i <= gb.size; i++) {
|
||||
if (i == gb.gap_start) {
|
||||
uint32_t ix = get_font_ix(font, ' ');
|
||||
@ -97,7 +109,41 @@ cursor_advance render_primary_buffer(ta_parameter_writer& writer,
|
||||
return cursor;
|
||||
}
|
||||
|
||||
void render_cursor(ta_parameter_writer& parameter,
|
||||
void render_text(ta_parameter_writer& writer,
|
||||
const font * font,
|
||||
const glyph * glyphs,
|
||||
const char * buf,
|
||||
int length,
|
||||
int32_t x0,
|
||||
int32_t y0)
|
||||
{
|
||||
int32_t h_advance = 0;
|
||||
int32_t v_advance = 0;
|
||||
|
||||
const float r_texture_width = 1.0f / font->texture_width;
|
||||
const float r_texture_height = 1.0f / font->texture_height;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
int32_t x = x0 + int_26_6(h_advance);
|
||||
int32_t y = y0 + int_26_6(v_advance);
|
||||
|
||||
char_type c = buf[i];
|
||||
uint32_t ix = get_font_ix(font, c);
|
||||
auto& glyph = glyphs[ix];
|
||||
|
||||
transform_glyph(writer,
|
||||
r_texture_width,
|
||||
r_texture_height,
|
||||
glyph,
|
||||
x,
|
||||
y
|
||||
);
|
||||
|
||||
h_advance += glyph.metrics.horiAdvance;
|
||||
}
|
||||
}
|
||||
|
||||
void render_cursor(ta_parameter_writer& writer,
|
||||
const cursor_advance& cursor,
|
||||
const viewport_window& window)
|
||||
{
|
||||
@ -106,7 +152,7 @@ void render_cursor(ta_parameter_writer& parameter,
|
||||
float width = int_26_6(cursor.width);
|
||||
float height = int_26_6(cursor.height);
|
||||
|
||||
transform_cursor(parameter,
|
||||
transform_cursor(writer,
|
||||
x, // x
|
||||
y, // y
|
||||
width,
|
||||
@ -114,6 +160,39 @@ void render_cursor(ta_parameter_writer& parameter,
|
||||
);
|
||||
}
|
||||
|
||||
static inline int copy_str(const char * s, char * d, int d_ix)
|
||||
{
|
||||
while (*s != 0) {
|
||||
d[d_ix++] = *s++;
|
||||
}
|
||||
return d_ix;
|
||||
}
|
||||
|
||||
void render_status(ta_parameter_writer& writer,
|
||||
const font * font,
|
||||
const glyph * glyphs,
|
||||
const gap_buffer& gb,
|
||||
const viewport_window& window)
|
||||
{
|
||||
char buf[256];
|
||||
int ix = 0;
|
||||
|
||||
ix = copy_str("(", buf, ix);
|
||||
ix += unparse_base10(&buf[ix], gb.line.gap, 0, 0);
|
||||
ix = copy_str(",", buf, ix);
|
||||
ix += unparse_base10(&buf[ix], gap_column_number(gb), 0, 0);
|
||||
ix = copy_str(") ", buf, ix);
|
||||
ix += unparse_base10(&buf[ix], window.first_line, 0, 0);
|
||||
|
||||
render_text(writer,
|
||||
font,
|
||||
glyphs,
|
||||
buf,
|
||||
ix,
|
||||
window.box.x0,
|
||||
480 - int_26_6(font->face_metrics.height) * 2);
|
||||
}
|
||||
|
||||
void render(ta_parameter_writer& writer,
|
||||
const font * font,
|
||||
const glyph * glyphs,
|
||||
@ -124,6 +203,8 @@ void render(ta_parameter_writer& writer,
|
||||
font->texture_width,
|
||||
font->texture_height);
|
||||
|
||||
render_status(writer, font, glyphs, gb, window);
|
||||
|
||||
cursor_advance cursor = render_primary_buffer(writer, font, glyphs, gb, window);
|
||||
|
||||
render_cursor(writer, cursor, window);
|
||||
|
@ -256,7 +256,7 @@ void main()
|
||||
struct editor_state state = { 0 };
|
||||
gap_init_from_buf(state.gb, buf, buf_size, 0);
|
||||
line_init_from_buf(state.gb, offsets, offsets_size);
|
||||
viewport_init_fullscreen(state.window);
|
||||
viewport_init_fullscreen(state.window, font);
|
||||
|
||||
ft6::data_transfer::data_format keyboards[2] = { 0 };
|
||||
|
||||
@ -269,7 +269,7 @@ void main()
|
||||
while (true) {
|
||||
keyboard_do_get_condition(keyboards[frame_ix & 1]);
|
||||
keyboard_debug(keyboards, frame_ix);
|
||||
keyboard_update(keyboards, frame_ix, state.gb);
|
||||
keyboard_update(keyboards, frame_ix, state.gb, state.window);
|
||||
|
||||
ta_polygon_converter_init2(texture_memory_alloc.isp_tsp_parameters[0].start,
|
||||
texture_memory_alloc.isp_tsp_parameters[0].end,
|
||||
|
@ -4,6 +4,7 @@ TEXT_EDITOR_OBJ = \
|
||||
text_editor/render.o \
|
||||
text_editor/keyboard.o \
|
||||
text_editor/transform.o \
|
||||
text_editor/unparse.o \
|
||||
holly/video_output.o \
|
||||
holly/core.o \
|
||||
holly/region_array.o \
|
||||
|
@ -204,6 +204,6 @@ void transform_glyph(ta_parameter_writer& writer,
|
||||
}
|
||||
|
||||
const float z = 0.1f;
|
||||
uint32_t base_color = 0xff0080ff;
|
||||
uint32_t base_color = 0xffffff;
|
||||
transfer_quad_type_3(writer, out[0], out[1], out[2], out[3], z, base_color);
|
||||
}
|
||||
|
165
text_editor/unparse.cpp
Normal file
165
text_editor/unparse.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
#include "minmax.hpp"
|
||||
#include "unparse.hpp"
|
||||
|
||||
int digits_base10(uint32_t n)
|
||||
{
|
||||
if (n >= 1000000000ul) return 10;
|
||||
if (n >= 100000000ul) return 9;
|
||||
if (n >= 10000000ul) return 8;
|
||||
if (n >= 1000000ul) return 7;
|
||||
if (n >= 100000ul) return 6;
|
||||
if (n >= 10000ul) return 5;
|
||||
if (n >= 1000ul) return 4;
|
||||
if (n >= 100ul) return 3;
|
||||
if (n >= 10ul) return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unparse_base10_unsigned(char * s, uint32_t n, int len, char fill)
|
||||
{
|
||||
int digits = 0;
|
||||
digits += digits_base10(n);
|
||||
len = max(digits, len);
|
||||
int ret = len;
|
||||
|
||||
while (len > digits) {
|
||||
*s++ = fill;
|
||||
--len;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
const uint32_t digit = n % 10;
|
||||
n = n / 10;
|
||||
s[--len] = digit + 48;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int unparse_base10(char * s, int32_t n, int len, char fill)
|
||||
{
|
||||
bool negative = false;
|
||||
int digits = 0;
|
||||
if (n < 0) {
|
||||
digits += 1;
|
||||
n = -n;
|
||||
negative = true;
|
||||
}
|
||||
|
||||
digits += digits_base10(n);
|
||||
len = max(digits, len);
|
||||
int ret = len;
|
||||
|
||||
while (len > digits) {
|
||||
*s++ = fill;
|
||||
--len;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
*s++ = '-';
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
const uint32_t digit = n % 10;
|
||||
n = n / 10;
|
||||
s[--len] = digit + 48;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int digits_base10_64(uint64_t n)
|
||||
{
|
||||
if (n >= 10000000000000000000ull) return 20;
|
||||
if (n >= 1000000000000000000ull) return 19;
|
||||
if (n >= 100000000000000000ull) return 18;
|
||||
if (n >= 10000000000000000ull) return 17;
|
||||
if (n >= 1000000000000000ull) return 16;
|
||||
if (n >= 100000000000000ull) return 15;
|
||||
if (n >= 10000000000000ull) return 14;
|
||||
if (n >= 1000000000000ull) return 13;
|
||||
if (n >= 100000000000ull) return 12;
|
||||
if (n >= 10000000000ull) return 11;
|
||||
if (n >= 1000000000ull) return 10;
|
||||
if (n >= 100000000ull) return 9;
|
||||
if (n >= 10000000ull) return 8;
|
||||
if (n >= 1000000ull) return 7;
|
||||
if (n >= 100000ull) return 6;
|
||||
if (n >= 10000ull) return 5;
|
||||
if (n >= 1000ull) return 4;
|
||||
if (n >= 100ull) return 3;
|
||||
if (n >= 10ull) return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unparse_base10_64(char * s, int64_t n, int len, char fill)
|
||||
{
|
||||
bool negative = false;
|
||||
int digits = 0;
|
||||
if (n < 0) {
|
||||
digits += 1;
|
||||
n = -n;
|
||||
negative = true;
|
||||
}
|
||||
|
||||
digits += digits_base10_64(n);
|
||||
len = max(digits, len);
|
||||
int ret = len;
|
||||
|
||||
while (len > digits) {
|
||||
*s++ = fill;
|
||||
--len;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
*s++ = '-';
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
const uint32_t digit = n % 10;
|
||||
n = n / 10;
|
||||
s[--len] = digit + 48;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int digits_base16(uint32_t n)
|
||||
{
|
||||
if (n <= 0xf) return 1;
|
||||
if (n <= 0xff) return 2;
|
||||
if (n <= 0xfff) return 3;
|
||||
if (n <= 0xffff) return 4;
|
||||
if (n <= 0xfffff) return 5;
|
||||
if (n <= 0xffffff) return 6;
|
||||
if (n <= 0xfffffff) return 7;
|
||||
return 8;
|
||||
}
|
||||
|
||||
int unparse_base16(char * s, uint32_t n, int len, char fill)
|
||||
{
|
||||
int digits = digits_base16(n);
|
||||
len = max(digits, len);
|
||||
int ret = len;
|
||||
|
||||
while (len > digits) {
|
||||
*s++ = fill;
|
||||
--len;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
uint32_t nib = n & 0xf;
|
||||
n = n >> 4;
|
||||
if (nib > 9) {
|
||||
nib += (97 - 10);
|
||||
} else {
|
||||
nib += (48 - 0);
|
||||
}
|
||||
|
||||
s[--len] = nib;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
8
text_editor/unparse.hpp
Normal file
8
text_editor/unparse.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int unparse_base10_unsigned(char * s, uint32_t n, int len, char fill);
|
||||
int unparse_base10(char * s, int32_t n, int len, char fill);
|
||||
int unparse_base10_64(char * s, int64_t n, int len, char fill);
|
||||
int unparse_base16(char * s, uint32_t n, int len, char fill);
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "font/font.h"
|
||||
|
||||
struct viewport_window {
|
||||
int32_t first_line;
|
||||
struct {
|
||||
@ -12,11 +14,11 @@ struct viewport_window {
|
||||
} box;
|
||||
};
|
||||
|
||||
inline void viewport_init_fullscreen(viewport_window& window)
|
||||
static inline void viewport_init_fullscreen(viewport_window& window, const font * font)
|
||||
{
|
||||
window.first_line = 0;
|
||||
window.box.x0 = 10;
|
||||
window.box.y0 = 20;
|
||||
window.box.x1 = 640 - 10;
|
||||
window.box.y1 = 480 - 20;
|
||||
window.box.y1 = 480 - (font->face_metrics.height >> 6) * 2;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user