2023-11-13 21:03:29 -05:00
|
|
|
/*
|
|
|
|
Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic
|
|
|
|
|
|
|
|
Xhartae 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef CHAPTER_4_SOURCE
|
|
|
|
#define CHAPTER_4_SOURCE
|
|
|
|
|
|
|
|
#include "chapter_4.h"
|
|
|
|
|
|
|
|
/*
|
2023-11-16 10:13:23 -05:00
|
|
|
Of course, we could just write something like 'preview_unhighlighted_text_file' function (name is obviously a joke), but this would stylize (apply colour and effect character
|
|
|
|
attributes) to our entire text file. When we're writing programs, syntax highlighting makes a lot of difference to readability, the same way the code formatting does, and initial
|
|
|
|
program design structure. If you use a lot of external variables everywhere, the entire programs starts to be messy or difficult to maintain, write and debug (or both). However,
|
|
|
|
if you use a lot of variables, and you pass each of them separately into functions, or if you have one huge monolithic structure (this time literal 'struct), you aren't doing
|
|
|
|
much better, except the compiler will have easier time to optimize your code, even tho that kind of code becomes pain to write. So, having few external functions, that do one
|
|
|
|
thing well, and having few external variables, that won't be edited outside of that file is the best in my opinion.
|
|
|
|
|
|
|
|
Your function calls won't be long, if you don't want to make those external ("global") variables visible to some other file, just move them to C source file instead of C header
|
|
|
|
file, and redeclare them as 'static', making them internal variables. Keep in mind, you have to use brain more in that case, and think about what you're modifying, where and why.
|
|
|
|
Well, if you want to write programs, and not to think about them, just close this and read Jin Ping Mei instead or something. There's no cheatsheet for making good programs, you
|
|
|
|
choose your constraints, your program design structure, and you start working on it.
|
|
|
|
|
|
|
|
@C
|
|
|
|
void preview_unhighlighted_text_file (char * text_file, int x, int y) {
|
2023-11-15 16:10:08 -05:00
|
|
|
char * text_data;
|
|
|
|
|
|
|
|
text_data = file_record (text_file);
|
|
|
|
|
2023-11-16 10:13:23 -05:00
|
|
|
for (curses_active = 1; curses_active != 0; ) {
|
2023-11-15 16:10:08 -05:00
|
|
|
curses_render_background (' ', COLOUR_WHITE, EFFECT_NORMAL);
|
|
|
|
curses_render_string (text_data, COLOUR_WHITE, EFFECT_NORMAL, x, x);
|
|
|
|
|
|
|
|
curses_synchronize ();
|
|
|
|
}
|
|
|
|
|
|
|
|
text_data = deallocate (text_data);
|
|
|
|
}
|
2023-11-16 10:13:23 -05:00
|
|
|
@
|
2023-11-13 21:03:29 -05:00
|
|
|
*/
|
|
|
|
|
2023-11-16 10:13:23 -05:00
|
|
|
static int syntax_count = 0;
|
|
|
|
static int syntax_active = 0;
|
|
|
|
static int * syntax_enrange = NULL;
|
|
|
|
static int * syntax_derange = NULL;
|
|
|
|
static char * * syntax_begin = NULL;
|
|
|
|
static char * * syntax_end = NULL;
|
|
|
|
static char * syntax_escape = NULL;
|
|
|
|
static int * syntax_colour = NULL;
|
|
|
|
static int * syntax_effect = NULL;
|
|
|
|
static char * syntax_separator = NULL;
|
|
|
|
|
|
|
|
static void syntax_delete (void) {
|
|
|
|
if (syntax_active == FALSE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
--syntax_count;
|
|
|
|
|
|
|
|
do {
|
|
|
|
syntax_begin [syntax_count] = deallocate (syntax_begin [syntax_count]);
|
|
|
|
syntax_end [syntax_count] = deallocate (syntax_end [syntax_count]);
|
|
|
|
} while (--syntax_count != -1);
|
|
|
|
|
|
|
|
syntax_enrange = deallocate (syntax_enrange);
|
|
|
|
syntax_derange = deallocate (syntax_derange);
|
|
|
|
syntax_begin = deallocate (syntax_begin);
|
|
|
|
syntax_end = deallocate (syntax_end);
|
|
|
|
syntax_escape = deallocate (syntax_escape);
|
|
|
|
syntax_colour = deallocate (syntax_colour);
|
|
|
|
syntax_effect = deallocate (syntax_effect);
|
|
|
|
syntax_separator = deallocate (syntax_separator);
|
|
|
|
|
|
|
|
syntax_active = FALSE;
|
|
|
|
syntax_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int syntax_define (int enrange, int derange, char * begin, char * end, char escape, int colour, int effect) {
|
|
|
|
if (syntax_active == FALSE) {
|
|
|
|
syntax_active = TRUE;
|
|
|
|
|
|
|
|
atexit (syntax_delete);
|
|
|
|
}
|
|
|
|
|
|
|
|
fatal_failure (begin == NULL, "syntax_define: Begin string is null pointer.");
|
|
|
|
fatal_failure (end == NULL, "syntax_define: End string is null pointer.");
|
|
|
|
|
|
|
|
++syntax_count;
|
|
|
|
|
|
|
|
syntax_enrange = reallocate (syntax_enrange, syntax_count * (int) sizeof (* syntax_enrange));
|
|
|
|
syntax_derange = reallocate (syntax_derange, syntax_count * (int) sizeof (* syntax_derange));
|
|
|
|
syntax_begin = reallocate (syntax_begin, syntax_count * (int) sizeof (* syntax_begin));
|
|
|
|
syntax_end = reallocate (syntax_end, syntax_count * (int) sizeof (* syntax_end));
|
|
|
|
syntax_escape = reallocate (syntax_escape, syntax_count * (int) sizeof (* syntax_escape));
|
|
|
|
syntax_colour = reallocate (syntax_colour, syntax_count * (int) sizeof (* syntax_colour));
|
|
|
|
syntax_effect = reallocate (syntax_effect, syntax_count * (int) sizeof (* syntax_effect));
|
|
|
|
|
|
|
|
syntax_begin [syntax_count - 1] = allocate ((string_length (begin) + 1) * (int) sizeof (* * syntax_begin));
|
|
|
|
syntax_end [syntax_count - 1] = allocate ((string_length (end) + 1) * (int) sizeof (* * syntax_end));
|
|
|
|
|
|
|
|
syntax_enrange [syntax_count - 1] = enrange;
|
|
|
|
syntax_derange [syntax_count - 1] = derange;
|
|
|
|
syntax_escape [syntax_count - 1] = escape;
|
|
|
|
syntax_colour [syntax_count - 1] = colour;
|
|
|
|
syntax_effect [syntax_count - 1] = effect;
|
|
|
|
|
|
|
|
string_copy (syntax_begin [syntax_count - 1], begin);
|
|
|
|
string_copy (syntax_end [syntax_count - 1], end);
|
|
|
|
|
|
|
|
return (syntax_count - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int syntax_select (char * string, int * length) {
|
|
|
|
int offset = 0;
|
|
|
|
int select = 0;
|
|
|
|
|
|
|
|
fatal_failure (syntax_active == FALSE, "Syntax is not active.");
|
|
|
|
|
|
|
|
fatal_failure (string == NULL, "syntax_select: String is null.");
|
|
|
|
fatal_failure (length == NULL, "syntax_select: Length is null.");
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (syntax_enrange [select] == 0) {
|
|
|
|
if (string_compare_limit (string, syntax_begin [select], string_length (syntax_begin [select])) != 0) {
|
|
|
|
if (syntax_derange [select] == 0) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
if (character_compare_array (string [string_length (syntax_begin [select])], syntax_end [select]) != 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int subset = 0;
|
|
|
|
do {
|
|
|
|
if (string [offset] == syntax_begin [select] [subset]) {
|
|
|
|
goto selected;
|
|
|
|
}
|
|
|
|
} while (++subset != (int) string_length (syntax_begin [select]));
|
|
|
|
}
|
|
|
|
} while (++select != syntax_count);
|
|
|
|
|
|
|
|
selected:
|
|
|
|
|
|
|
|
if (select == syntax_count) {
|
|
|
|
* length = 1;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
++offset;
|
|
|
|
|
|
|
|
if (string [offset] == syntax_escape [select]) {
|
|
|
|
++offset;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (syntax_derange [select] == 0) {
|
|
|
|
if (string_compare_limit (& string [offset], syntax_end [select], string_length (syntax_end [select]))) {
|
|
|
|
* length = offset + string_length (syntax_end [select]);
|
|
|
|
return (select);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int subset = 0;
|
|
|
|
if (string_compare (syntax_end [select], "") == 0) {
|
|
|
|
break;
|
|
|
|
} do {
|
|
|
|
if (string [offset] == syntax_end [select] [subset]) {
|
|
|
|
* length = offset;
|
|
|
|
return (select);
|
|
|
|
}
|
|
|
|
} while (++subset != (int) string_length (syntax_end [select]));
|
|
|
|
}
|
|
|
|
} while (string [offset - 1] != '\0');
|
|
|
|
|
|
|
|
return (select);
|
|
|
|
}
|
|
|
|
|
|
|
|
void preview_c_file (char * text_file, int width, int height, int x, int y) {
|
2023-11-13 21:03:29 -05:00
|
|
|
char * text_data;
|
|
|
|
|
2023-11-15 16:10:08 -05:00
|
|
|
int reset_x = x;
|
|
|
|
int reset_y = y;
|
|
|
|
|
2023-11-13 21:03:29 -05:00
|
|
|
text_data = file_record (text_file);
|
|
|
|
|
2023-11-16 10:13:23 -05:00
|
|
|
for (curses_active = 1; curses_active != 0; ) {
|
2023-11-15 16:10:08 -05:00
|
|
|
int offset, colour, effect, string;
|
|
|
|
|
2023-11-13 21:03:29 -05:00
|
|
|
curses_render_background (' ', COLOUR_WHITE, EFFECT_NORMAL);
|
2023-11-15 16:10:08 -05:00
|
|
|
|
|
|
|
x = reset_x;
|
|
|
|
y = reset_y;
|
|
|
|
|
|
|
|
string = 0;
|
|
|
|
colour = COLOUR_WHITE;
|
|
|
|
effect = EFFECT_NORMAL;
|
|
|
|
|
|
|
|
for (offset = 0; offset != string_length (text_data); ++offset) {
|
|
|
|
switch (text_data [offset]) {
|
|
|
|
case '"':
|
|
|
|
string = ! string;
|
|
|
|
colour = (string != 0) ? COLOUR_RED : COLOUR_WHITE;
|
|
|
|
effect = (string != 0) ? EFFECT_BOLD : EFFECT_NORMAL;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
curses_render_character (text_data [offset], colour, effect, x, y);
|
|
|
|
|
|
|
|
switch (text_data [offset]) {
|
|
|
|
case '\t': x += 8; break;
|
|
|
|
case '\n': y += 1; x = reset_x; break;
|
|
|
|
default: x += 1; break;
|
|
|
|
}
|
|
|
|
}
|
2023-11-13 21:03:29 -05:00
|
|
|
|
|
|
|
curses_synchronize ();
|
|
|
|
}
|
|
|
|
|
|
|
|
text_data = deallocate (text_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|