209 lines
4.2 KiB
C
209 lines
4.2 KiB
C
|
|
#include "viewer.h"
|
||
|
|
#include "file.h"
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
|
||
|
|
int out_x, out_y;
|
||
|
|
int cursor_x, cursor_y;
|
||
|
|
char* displaying_buffer;
|
||
|
|
int working_with_offset;
|
||
|
|
|
||
|
|
static int _viewer_get_offset(int cx, int cy)
|
||
|
|
{
|
||
|
|
return cy * SCREEN_X + cx;
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_clear_screen()
|
||
|
|
{
|
||
|
|
out_x = out_y = 0;
|
||
|
|
write(STDOUT, "\x1b[2J", 4);
|
||
|
|
write(STDOUT, "\x1b[H", 3);
|
||
|
|
}
|
||
|
|
|
||
|
|
void _viewer_set_cursor(int col, int row)
|
||
|
|
{
|
||
|
|
char buf[8];
|
||
|
|
buf[0] = '\x1b';
|
||
|
|
buf[1] = '[';
|
||
|
|
int id = 2;
|
||
|
|
col++, row++;
|
||
|
|
if (row < 10) {
|
||
|
|
buf[id++] = row + '0';
|
||
|
|
} else {
|
||
|
|
buf[id++] = (row / 10) + '0';
|
||
|
|
buf[id++] = (row % 10) + '0';
|
||
|
|
}
|
||
|
|
buf[id++] = ';';
|
||
|
|
if (col < 10) {
|
||
|
|
buf[id++] = col + '0';
|
||
|
|
} else {
|
||
|
|
buf[id++] = (col / 10) + '0';
|
||
|
|
buf[id++] = (col % 10) + '0';
|
||
|
|
}
|
||
|
|
buf[id++] = 'H';
|
||
|
|
write(STDOUT, buf, id);
|
||
|
|
}
|
||
|
|
|
||
|
|
void _viewer_set_cursor_to_start()
|
||
|
|
{
|
||
|
|
write(STDOUT, "\x1b[H", 3);
|
||
|
|
}
|
||
|
|
|
||
|
|
void _viewer_new_line()
|
||
|
|
{
|
||
|
|
write(STDOUT, "\n", 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
char _viewer_has_space_to_print(char c)
|
||
|
|
{
|
||
|
|
if (c == '\n') {
|
||
|
|
if (out_y == SCREEN_Y - 1) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (out_x == SCREEN_X - 1 && out_y == SCREEN_Y - 1) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
char _viewer_display_one(char c)
|
||
|
|
{
|
||
|
|
if (_viewer_has_space_to_print(c)) {
|
||
|
|
if (c == '\n') {
|
||
|
|
out_x = 0;
|
||
|
|
out_y++;
|
||
|
|
_viewer_new_line();
|
||
|
|
} else {
|
||
|
|
write(STDOUT, &c, 1);
|
||
|
|
out_x++;
|
||
|
|
if (out_x == SCREEN_X) {
|
||
|
|
out_x = 0;
|
||
|
|
out_y++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void _log_dec(uint32_t dec)
|
||
|
|
{
|
||
|
|
uint32_t pk = 1000000000;
|
||
|
|
char was_not_zero = 0;
|
||
|
|
while (pk > 0) {
|
||
|
|
uint32_t pp = dec / pk;
|
||
|
|
if (was_not_zero || pp > 0) {
|
||
|
|
char ccp = pp + '0';
|
||
|
|
write(1, &ccp, 1);
|
||
|
|
was_not_zero = 1;
|
||
|
|
}
|
||
|
|
dec -= pp * pk;
|
||
|
|
pk /= 10;
|
||
|
|
}
|
||
|
|
if (!was_not_zero) {
|
||
|
|
write(1, "0", 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_display(char* buf, int start, int len)
|
||
|
|
{
|
||
|
|
displaying_buffer = buf;
|
||
|
|
int last_cx = 0;
|
||
|
|
viewer_clear_screen();
|
||
|
|
for (int i = start; i < start + len; i++) {
|
||
|
|
if (out_x <= cursor_x && out_y == cursor_y) {
|
||
|
|
working_with_offset = i;
|
||
|
|
last_cx = out_x;
|
||
|
|
}
|
||
|
|
if (!_viewer_display_one(buf[i])) {
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
while (out_y < SCREEN_Y - 1) {
|
||
|
|
out_y++;
|
||
|
|
write(STDOUT, "\n~", 2);
|
||
|
|
}
|
||
|
|
out:
|
||
|
|
cursor_x = last_cx;
|
||
|
|
_viewer_set_cursor(cursor_x, cursor_y);
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_cursor_left()
|
||
|
|
{
|
||
|
|
if (cursor_x) {
|
||
|
|
cursor_x--;
|
||
|
|
working_with_offset--;
|
||
|
|
_viewer_set_cursor(cursor_x, cursor_y);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_cursor_right()
|
||
|
|
{
|
||
|
|
if (displaying_buffer) {
|
||
|
|
if (displaying_buffer[working_with_offset] != '\n') {
|
||
|
|
cursor_x++;
|
||
|
|
working_with_offset++;
|
||
|
|
_viewer_set_cursor(cursor_x, cursor_y);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_cursor_up()
|
||
|
|
{
|
||
|
|
if (!cursor_y) {
|
||
|
|
file_scroll_up();
|
||
|
|
} else {
|
||
|
|
working_with_offset -= file_line_len_backwards(working_with_offset);
|
||
|
|
cursor_y--;
|
||
|
|
int new_line_len = file_line_len_backwards(working_with_offset) - 1;
|
||
|
|
if (cursor_x >= new_line_len) {
|
||
|
|
cursor_x = (new_line_len) % SCREEN_X;
|
||
|
|
}
|
||
|
|
working_with_offset -= (new_line_len);
|
||
|
|
working_with_offset += cursor_x;
|
||
|
|
_viewer_set_cursor(cursor_x, cursor_y);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_cursor_down()
|
||
|
|
{
|
||
|
|
if (cursor_y == SCREEN_Y - 1) {
|
||
|
|
file_scroll_down();
|
||
|
|
} else {
|
||
|
|
working_with_offset += file_line_len(working_with_offset);
|
||
|
|
cursor_y++;
|
||
|
|
if (cursor_x >= file_line_len(working_with_offset)) {
|
||
|
|
cursor_x = file_line_len(working_with_offset) - 1;
|
||
|
|
}
|
||
|
|
working_with_offset += cursor_x;
|
||
|
|
_viewer_set_cursor(cursor_x, cursor_y);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_cursor_next()
|
||
|
|
{
|
||
|
|
cursor_x++;
|
||
|
|
if (cursor_x == SCREEN_X) {
|
||
|
|
cursor_y++;
|
||
|
|
cursor_x = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int viewer_get_cursor_offset_in_file()
|
||
|
|
{
|
||
|
|
return working_with_offset;
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_enter_menu_mode()
|
||
|
|
{
|
||
|
|
write(STDOUT, "\x1b[25;1H", 7);
|
||
|
|
}
|
||
|
|
|
||
|
|
void viewer_leave_menu_mode()
|
||
|
|
{
|
||
|
|
/* FIXME: Restore cursor to prev position */
|
||
|
|
_viewer_set_cursor_to_start();
|
||
|
|
}
|