diff --git a/chapter/chapter_4.c b/chapter/chapter_4.c index 9401c11..bcc545a 100644 --- a/chapter/chapter_4.c +++ b/chapter/chapter_4.c @@ -12,15 +12,25 @@ It is distributed in the hope that it will be useful or harmful, it really depen #include "chapter_4.h" /* +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. -void program_view_c_file (char * text_file, int width, int height, int x, int y) { +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) { char * text_data; - curses_active = 1; - text_data = file_record (text_file); - while (curses_active != 0) { + for (curses_active = 1; curses_active != 0; ) { curses_render_background (' ', COLOUR_WHITE, EFFECT_NORMAL); curses_render_string (text_data, COLOUR_WHITE, EFFECT_NORMAL, x, x); @@ -29,20 +39,156 @@ void program_view_c_file (char * text_file, int width, int height, int x, int y) text_data = deallocate (text_data); } - +@ */ -void program_view_c_file (char * text_file, int width, int height, int x, int y) { +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) { char * text_data; int reset_x = x; int reset_y = y; - curses_active = 1; - text_data = file_record (text_file); - while (curses_active != 0) { + for (curses_active = 1; curses_active != 0; ) { int offset, colour, effect, string; curses_render_background (' ', COLOUR_WHITE, EFFECT_NORMAL); diff --git a/chapter/chapter_4.h b/chapter/chapter_4.h index 96ecd5d..4567c8a 100644 --- a/chapter/chapter_4.h +++ b/chapter/chapter_4.h @@ -17,7 +17,7 @@ It is distributed in the hope that it will be useful or harmful, it really depen /* I believe that this chapter should be a breakpoint for you to write a simple C program. So far, we've learned in: -- chapter 0: To format our code properly in order to increase readability and we've implemented some core functions for memory, strings and input / output. +- chapter 0: To format our code properly in order to increase readability and we've implemented some core functions for memory management, strings and input / output. - chapter 1: To declare and define functions, and we've covered character and file descriptor related functions, as well as ASCII table and discussed C keywords. - chapter 2: To use external variables, function pointers and minor part of 'libncurses' reimplementation that doesn't care about portability. - chapter 3: To use standard library 'printf' function, and to implement variadic argument functions, while also covering switch statement in more depth. @@ -27,12 +27,12 @@ example, some of them will require functions from some or all previous chapter s chapters. Instead of that, we'll (re)implement newer stuff with different approach if necessary. That way, you can be sure that if you're reading chapter four, for example, it'll only use functions and variables defined in chapters zero to three. Lets begin. -I'll write this huge 'program_view_c_file' function in procedural style, so to say, and in the next chapter, we'll reimplement it in more modular way, using other (sub)programs, -or simply, functions. Learning anything, including the C programming language, is like a journey. Maybe you think it won't last long, and it ends up being quite long journey, or -maybe you think it'll be very long, that you'll walk miles and miles, and it ends up being short (you rage-quit). The final destination you're going towards always depends on -where you left-off, where you're coming from. For example, if you wrote Ada, you'll like chapter four, if you wrote C++, you'll like chapter five. +I'll write this huge 'preview_c_file' function in procedural style, so to say, and in the next chapter, we'll reimplement it in more modular way, using other functions. Learning +anything, including the C programming language, is like a journey. Maybe you think it won't last long, and it ends up being quite long journey, or maybe you think it'll be very +long, that you'll walk miles and miles, and it ends up being short (you rage-quit). The final destination you're going towards always depends on where you left-off, where you're +coming from. For example, if you wrote Ada, you'll like chapter four, if you wrote C++, you'll like chapter five. */ -extern void program_view_c_file (char * text_file, int width, int height, int x, int y); +extern void preview_c_file (char * text_file, int width, int height, int x, int y); #endif diff --git a/xhartae.c b/xhartae.c index 500a991..c6f2691 100644 --- a/xhartae.c +++ b/xhartae.c @@ -130,7 +130,9 @@ int main (int argc, char * * argv) { curses_configure (); - while (curses_active != 0) { + // We could simply write a while loop, but I prefer to be consistent with using for loops, and not to rely on default comparison to zero. + // while (curses_active) { ... + for (; curses_active != 0; ) { curses_render_background ('.', COLOUR_GREY, EFFECT_BOLD); curses_render_character ('@', COLOUR_RED, EFFECT_BOLD, 1, 1); curses_render_string ("Heyo world!", COLOUR_GREEN, EFFECT_ITALIC, 2, 2); @@ -139,7 +141,7 @@ int main (int argc, char * * argv) { curses_synchronize (); } - program_view_c_file ("program/hello_world.c", curses_screen_width, curses_screen_height, 0, 0); + preview_c_file ("program/hello_world.c", curses_screen_width, curses_screen_height, 0, 0); return (EXIT_SUCCESS); }