xource/xource.c
2023-10-29 14:14:13 -04:00

238 lines
7.0 KiB
C

/*
Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic
Xource is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation.
And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version.
It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3.
*/
#include <xolatile/xtandard.c>
#include <xolatile/xyntax.c>
#include <xolatile/xurses.c>
enum {
MODE_NONE, MODE_INSERT, MODE_COMMAND,
MODE_COUNT
};
static int cursor = 0;
static int cursor_x = 0;
static int cursor_y = 0;
static int mode_active = MODE_INSERT;
static void append_character (void) {
int offset = 0;
++file_list_size [file_list_active];
file_list_data [file_list_active] = reallocate (file_list_data [file_list_active], file_list_size [file_list_active]);
for (offset = file_list_size [file_list_active] - 1; offset != cursor; --offset) {
file_list_data [file_list_active] [offset] = file_list_data [file_list_active] [offset - 1];
}
file_list_data [file_list_active] [cursor] = curses_character;
++cursor;
}
static void remove_character (void) {
int offset = 0;
if (cursor == 0) {
return;
}
--file_list_size [file_list_active];
for (offset = cursor - 1; offset != file_list_size [file_list_active] - 1; ++offset) {
file_list_data [file_list_active] [offset] = file_list_data [file_list_active] [offset + 1];
}
--cursor;
}
static void cursor_limits (void) {
if (cursor <= -1) {
cursor = 0;
}
if (cursor >= file_list_size [file_list_active]) {
cursor = file_list_size [file_list_active] - 1;
}
}
static void mode_switch (void);
static void mode_none (void) {
curses_bind (SIGNAL_ESCAPE, mode_switch);
}
static void mode_insert (void) {
int signal;
for (signal = SIGNAL_A; signal != SIGNAL_COUNT; ++signal) {
if ((signal == SIGNAL_ESCAPE) || (signal == SIGNAL_BACKSPACE) || (signal == SIGNAL_CAPS_LOCK)) {
continue;
}
curses_bind (signal, append_character);
curses_bind (signal | SIGNAL_SHIFT, append_character);
}
curses_bind (SIGNAL_ESCAPE, mode_switch);
curses_bind (SIGNAL_BACKSPACE, remove_character);
}
static void mode_command (void) {
curses_bind (SIGNAL_ESCAPE, mode_switch);
}
static void mode_switch (void) {
curses_action = deallocate (curses_action);
curses_activator = deallocate (curses_activator);
curses_action_count = 0;
mode_active += 1;
mode_active %= MODE_COUNT;
switch (mode_active) {
case MODE_INSERT: mode_insert (); break;
case MODE_COMMAND: mode_command (); break;
default: mode_none (); break;
}
curses_bind (SIGNAL_ESCAPE | SIGNAL_SHIFT, curses_exit);
mode_active = mode_active;
}
static void render_status_bar (void) {
char status_bar [] = " Xource : C = Xolatile's text editor";
int offset;
curses_render_string (status_bar, mode_active, EFFECT_REVERSE, 0, 0);
for (offset = string_length (status_bar); offset != curses_screen_width; ++offset) {
curses_render_string (" ", mode_active, EFFECT_REVERSE, offset, 0);
}
for (offset = 1; offset != curses_screen_height; ++offset) {
curses_render_string (string_realign (number_to_string (offset), 4, ' '), mode_active, EFFECT_REVERSE, 0, offset);
}
}
static void render_source_code (void) {
int offset, select, length;
cursor_x = curses_realign_x = 5;
cursor_y = curses_realign_y = 1;
for (offset = 0; file_list_data [file_list_active] [offset] != '\0'; offset += length) {
if (cursor_y > curses_screen_height - 2) {
break;
}
select = syntax_select (& file_list_data [file_list_active] [offset], & length);
if (select >= syntax_count) {
curses_render_string_point (& file_list_data [file_list_active] [offset], length, COLOUR_WHITE, EFFECT_NORMAL, & cursor_x, & cursor_y);
} else {
curses_render_string_point (& file_list_data [file_list_active] [offset], length, syntax_colour [select], syntax_effect [select], & cursor_x, & cursor_y);
}
}
if (cursor_y < curses_screen_height) {
for (offset = ++cursor_y; offset != curses_screen_height; ++offset) {
curses_render_string (" ~", mode_active, EFFECT_REVERSE, 0, offset);
}
}
}
#include <stdio.h>
int main (int argc, char * * argv) {
char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n";
char * keywords [] = {
"register", "volatile", "auto", "const", "static", "extern", "if", "else",
"do", "while", "for", "continue", "switch", "case", "default", "break",
"enum", "union", "struct", "typedef", "goto", "void", "return", "sizeof",
"char", "short", "int", "long", "signed", "unsigned", "float", "double"
};
if (argc == 2) {
file_list_import (argv [1]);
} else {
out ("ARGUMENTS\n", 10);
return (-1);
}
syntax_define_separators (separators);
syntax_define_range ("/*", "*/", '\0', COLOUR_GREY, EFFECT_BOLD);
syntax_define_range ("//", "\n", '\0', COLOUR_GREY, EFFECT_BOLD);
syntax_define_range ("#", "\n", '\\', COLOUR_PINK, EFFECT_NORMAL);
syntax_define_range ("'", "'", '\\', COLOUR_PINK, EFFECT_BOLD);
syntax_define_operators (".,:;<=>+*-/%!&~^?|()[]{}", COLOUR_YELLOW, EFFECT_NORMAL);
syntax_define_words (keywords, sizeof (keywords) / sizeof (keywords [0]), COLOUR_YELLOW, EFFECT_BOLD);
syntax_define_default (1, COLOUR_RED, EFFECT_NORMAL, COLOUR_CYAN, EFFECT_BOLD);
curses_configure ();
/*mode_switch ();*/
do {
curses_render_background (' ', COLOUR_WHITE, EFFECT_NORMAL);
render_status_bar ();
render_source_code ();
curses_render_cursor (cursor_x, cursor_y);
curses_synchronize ();
/*
dump ("a.log", number_to_string (curses_character));
dump ("a.log", "\n");
*/
if (curses_character == ('Q' & 0X1F)) {
curses_active = 0;
} else if (curses_character == '\r') {
append_character ();
} else if (curses_character == ('S' & 0X1F)) {
file_list_export (file_list_name [file_list_active]);
} else if (curses_character == (char) 127) {
remove_character ();
} else if (curses_character == 0X415B1B) {
do {
--cursor;
} while ((cursor >= 0) && (file_list_data [file_list_active] [cursor] != '\n') && (file_list_data [file_list_active] [cursor] != '\0'));
--cursor;
} else if (curses_character == 0X425B1B) {
do {
++cursor;
} while ((cursor <= file_list_size [file_list_active] - 1) && (file_list_data [file_list_active] [cursor] != '\n') && (file_list_data [file_list_active] [cursor] != '\0'));
++cursor;
} else if (curses_character == 0X435B1B) {
++cursor;
} else if (curses_character == 0X445B1B) {
--cursor;
} else if ((curses_character >= ' ') && (curses_character <= '~')) {
append_character ();
} else {
continue;
}
cursor_limits ();
} while (curses_active != 0);
file_list_delete ();
syntax_delete ();
return (EXIT_SUCCESS);
}