diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Doxyfile | 23 | ||||
-rw-r--r-- | base.h | 54 | ||||
-rw-r--r-- | buffer.c | 3 | ||||
-rw-r--r-- | colors.h | 6 | ||||
-rw-r--r-- | command.h | 95 | ||||
-rw-r--r-- | ds.h | 56 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | os.h | 128 | ||||
-rw-r--r-- | ted.h | 1325 | ||||
-rw-r--r-- | text.h | 83 | ||||
-rw-r--r-- | unicode.h | 49 | ||||
-rw-r--r-- | util.h | 90 |
13 files changed, 1094 insertions, 823 deletions
@@ -33,3 +33,4 @@ UpgradeLog.htm compile_commands.json # clangd creates .cache on windows at least .cache +doc diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..a647a92 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,23 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = ted +PROJECT_BRIEF = "A text editor" +PROJECT_LOGO = assets/icon.ico +OUTPUT_DIRECTORY = doc +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +OPTIMIZE_OUTPUT_FOR_C = YES +MARKDOWN_SUPPORT = YES +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.h +RECURSIVE = NO +GENERATE_HTML = YES +HTML_OUTPUT = . +HTML_FILE_EXTENSION = .html +GENERATE_LATEX = NO +ENABLE_PREPROCESSING = YES +MULTILINE_CPP_IS_BRIEF = YES +AUTOLINK_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = YES +EXTRACT_STATIC = YE +COLLABORATION_GRAPH = NO +EXCLUDE = lsp.h, keywords.h, pcre-inc.h, sdl-inc.h @@ -1,5 +1,7 @@ -// basic types and macros. -// this file is included almost everywhere. +/// \file +/// basic types and macros. +/// +/// this file is included almost everywhere. #ifndef BASE_H_ #define BASE_H_ @@ -90,21 +92,15 @@ typedef unsigned long ulong; typedef long long llong; typedef unsigned long long ullong; -// allows -// switch (c) { -// case ANY_DIGIT: -// ... -// } +/// allows +/// ``` +/// switch (c) { +/// case ANY_DIGIT: +/// ... +/// } +/// ``` #define ANY_DIGIT '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9' -#if __clang__ -#define ENUM_U8 typedef enum : u8 -#define ENUM_U8_END(name) name -#else -#define ENUM_U8 enum -#define ENUM_U8_END(name) ; typedef u8 name -#endif - #ifdef __GNUC__ #define WarnUnusedResult __attribute__((warn_unused_result)) #else @@ -114,29 +110,23 @@ typedef unsigned long long ullong; #if __GNUC__ #define ATTRIBUTE_PRINTF(fmt_idx, arg_idx) __attribute__ ((format(printf, fmt_idx, arg_idx))) #else +/// attribute for functions which are like `printf` (to give `-Wformat` warnings) #define ATTRIBUTE_PRINTF(fmt_idx, arg_idx) #endif #if _MSC_VER > 1400 #define PRINTF_FORMAT_STRING _Printf_format_string_ #else +/// needed to give format warnings for MSVC for custom functions #define PRINTF_FORMAT_STRING #endif -// this type is an alias for bool, except that it -// produces a warning if it's not used. -// false = error, true = success +/// this type is an alias for bool, except that it +/// produces a warning if it's not used. +/// false = error, true = success #define Status bool WarnUnusedResult #define arr_count(a) (sizeof (a) / sizeof *(a)) - -// usage: if UNLIKELY (x > 2) ... -#if __GNUC__ -#define UNLIKELY(x) (__builtin_expect(x,0)) -#else -#define UNLIKELY(x) (x) -#endif - #ifdef __GNUC__ #define no_warn_start _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \ @@ -183,7 +173,8 @@ static void print(const char *fmt, ...) { // If you are adding new languages, DO NOT change the constant values // of the previous languages. It will mess up config files which use :set-language! typedef enum { - LANG_NONE = 0, // avoid using this and use LANG_TEXT instead. + /// avoid using this and use LANG_TEXT instead. + LANG_NONE = 0, LANG_C = 1, LANG_CPP = 2, LANG_RUST = 3, @@ -191,16 +182,19 @@ typedef enum { LANG_TEX = 5, LANG_MARKDOWN = 6, LANG_HTML = 7, - LANG_CONFIG = 8, // .cfg files + /// .cfg files + LANG_CONFIG = 8, LANG_JAVASCRIPT = 9, LANG_JAVA = 10, LANG_GO = 11, - LANG_TED_CFG = 12, // like LANG_CONFIG, but with multiline strings. + /// like \ref LANG_CONFIG, but with multiline strings. + LANG_TED_CFG = 12, LANG_TYPESCRIPT = 13, LANG_JSON = 14, LANG_XML = 15, LANG_GLSL = 16, - LANG_TEXT = 17, // plain text + /// plain text + LANG_TEXT = 17, LANG_COUNT } Language; @@ -441,8 +441,7 @@ static BufferPos buffer_pos_advance(TextBuffer *buffer, BufferPos pos, size_t nc } -// returns "p2 - p1", that is, the number of characters between p1 and p2. -static i64 buffer_pos_diff(TextBuffer *buffer, BufferPos p1, BufferPos p2) { +i64 buffer_pos_diff(TextBuffer *buffer, BufferPos p1, BufferPos p2) { assert(buffer_pos_valid(buffer, p1)); assert(buffer_pos_valid(buffer, p2)); @@ -1,8 +1,12 @@ -// colors enum. +/// \file +/// colors enum. #ifndef COLORS_H_ #define COLORS_H_ +/// colors enum. +/// +/// See `ted.cfg` for what these mean. typedef enum { COLOR_UNKNOWN, @@ -1,53 +1,75 @@ -// command enum +/// \file +/// command enum #ifndef COMMAND_H_ #define COMMAND_H_ -// `i | ARG_STRING` when used as an argument refers to `ted->strings[i]` +/// `i | ARG_STRING` when used as an argument refers to `ted->strings[i]` #define ARG_STRING 0x4000000000000000 +/// command enum +/// +/// more documentation in `ted.cfg`. typedef enum { CMD_UNKNOWN, - CMD_NOOP, // do nothing + /// do nothing + CMD_NOOP, // movement and selection commands - CMD_LEFT, // move cursor left - CMD_RIGHT, // move cursor right - CMD_UP, // move cursor up - CMD_DOWN, // move cursor down - CMD_SELECT_LEFT, // move cursor left, and select + /// move cursor left + CMD_LEFT, + /// move cursor right + CMD_RIGHT, + /// move cursor up + CMD_UP, + /// move cursor down + CMD_DOWN, + /// move cursor left, and select + CMD_SELECT_LEFT, CMD_SELECT_RIGHT, CMD_SELECT_UP, CMD_SELECT_DOWN, - CMD_LEFT_WORD, // move cursor left a word + /// move cursor left a word + CMD_LEFT_WORD, CMD_RIGHT_WORD, CMD_UP_BLANK_LINE, CMD_DOWN_BLANK_LINE, CMD_SELECT_LEFT_WORD, CMD_SELECT_RIGHT_WORD, - CMD_START_OF_LINE, // move cursor to start of line - CMD_END_OF_LINE, // move cursor to end of line - CMD_SELECT_START_OF_LINE, // select to start of line - CMD_SELECT_END_OF_LINE, // select to end of line - CMD_START_OF_FILE, // move cursor to start of buffer - CMD_END_OF_FILE, // move cursor to end of buffer + /// move cursor to start of line + CMD_START_OF_LINE, + /// move cursor to end of line + CMD_END_OF_LINE, + /// select to start of line + CMD_SELECT_START_OF_LINE, + /// select to end of line + CMD_SELECT_END_OF_LINE, + /// move cursor to start of buffer + CMD_START_OF_FILE, + /// move cursor to end of buffer + CMD_END_OF_FILE, CMD_SELECT_START_OF_FILE, CMD_SELECT_END_OF_FILE, - CMD_SELECT_ALL, // select entire buffer + /// select entire buffer + CMD_SELECT_ALL, CMD_SELECT_PAGE_UP, CMD_SELECT_PAGE_DOWN, CMD_SELECT_UP_BLANK_LINE, CMD_SELECT_DOWN_BLANK_LINE, // insertion - CMD_INSERT_TEXT, // insert text - CMD_TAB, // insert '\t' + /// insert text + CMD_INSERT_TEXT, + /// insert `\t` + CMD_TAB, CMD_BACKTAB, - CMD_NEWLINE, // insert '\n' + autoindent -- also used to submit line buffers + /// insert `\n` + autoindent -- also used to submit line buffers + CMD_NEWLINE, CMD_NEWLINE_BACK, CMD_COMMENT_SELECTION, // scrolling - CMD_PAGE_UP, // move cursor up one page up (where one page is however tall the buffer is) + /// move cursor up one page up (where one page is however tall the buffer is) + CMD_PAGE_UP, CMD_PAGE_DOWN, // deletion @@ -56,16 +78,20 @@ typedef enum { CMD_BACKSPACE_WORD, CMD_DELETE_WORD, - CMD_OPEN, // open a file - CMD_SAVE, // save current buffer + /// open a file + CMD_OPEN, + /// save current buffer + CMD_SAVE, CMD_SAVE_AS, - CMD_SAVE_ALL, // save all open buffers with unsaved changes + /// save all open buffers with unsaved changes + CMD_SAVE_ALL, CMD_NEW, CMD_UNDO, CMD_REDO, CMD_COMMAND_SELECTOR, CMD_OPEN_CONFIG, - CMD_RELOAD_ALL, // reload all buffers from file + /// reload all buffers from file + CMD_RELOAD_ALL, CMD_QUIT, // IDE features @@ -73,7 +99,8 @@ typedef enum { CMD_AUTOCOMPLETE, CMD_AUTOCOMPLETE_BACK, CMD_FIND_USAGES, - CMD_GOTO_DEFINITION, // "go to definition of..." menu + /// "go to definition of..." menu + CMD_GOTO_DEFINITION, CMD_GOTO_DEFINITION_AT_CURSOR, CMD_GOTO_DECLARATION_AT_CURSOR, CMD_GOTO_TYPE_DEFINITION_AT_CURSOR, @@ -86,7 +113,8 @@ typedef enum { CMD_FIND_REPLACE, CMD_TAB_CLOSE, - CMD_TAB_SWITCH, // argument = index of tab (starting at 0) + /// argument = index of tab (starting at 0) + CMD_TAB_SWITCH, CMD_TAB_NEXT, CMD_TAB_PREV, CMD_TAB_MOVE_LEFT, @@ -95,7 +123,8 @@ typedef enum { CMD_TEXT_SIZE_INCREASE, CMD_TEXT_SIZE_DECREASE, - CMD_VIEW_ONLY, // toggle view-only mode + /// toggle view-only mode + CMD_VIEW_ONLY, CMD_BUILD, CMD_BUILD_PREV_ERROR, @@ -103,15 +132,19 @@ typedef enum { CMD_SHELL, CMD_GENERATE_TAGS, - CMD_GOTO_LINE, // open "goto line..." menu + /// open "goto line..." menu + CMD_GOTO_LINE, CMD_SPLIT_HORIZONTAL, CMD_SPLIT_VERTICAL, CMD_SPLIT_JOIN, - CMD_SPLIT_SWITCH, // switch to the other side of a split - CMD_SPLIT_SWAP, // swap which side is which in a split. + /// switch to the other side of a split + CMD_SPLIT_SWITCH, + /// swap which side is which in a split. + CMD_SPLIT_SWAP, - CMD_ESCAPE, // by default this is the escape key. closes menus, etc. + /// by default this is the escape key. closes menus, etc. + CMD_ESCAPE, CMD_COUNT } Command; @@ -1,8 +1,7 @@ -#ifndef DS_H_ -#define DS_H_ +/*! +\file +\brief VARIOUS DATA STRUCTURES -/* -VARIOUS DATA STRUCTURES - dynamic array - string builder - string hash table @@ -13,7 +12,7 @@ any reasonable compiler will ignore the unused code. functions in this file suffixed with _ are not meant to be used outside here, unless you know what you're doing -NOTE: even on 64-bit platforms, dynamic arrays can only hold ~2^32 elements. +NOTE: even on 64-bit platforms, dynamic arrays can only hold ~2<sup>32</sup> elements. IMPORTANT NOTE: If you are using this with structures containing `long double`s, do #define ARR_LONG_DOUBLE @@ -23,6 +22,9 @@ IMPORTANT NOTE: If you are using this with structures containing `long double`s, which isnt important unless you're making a lot of arrays.) */ +#ifndef DS_H_ +#define DS_H_ + #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -208,19 +210,18 @@ static void *arr_copy_(const void *arr, size_t member_size) { #endif #define arr__join2(a,b) a##b -#define arr__join(a,b) arr__join2(a,b) // macro used internally -// if the array is not NULL, free it and set it to NULL +/// macro used internally +#define arr__join(a,b) arr__join2(a,b) +/// if the array is not NULL, free it and set it to NULL #define arr_free(a) do { if (a) { free(arr_hdr_(a)); (a) = NULL; } } while (0) -// a nice alias +/// a nice alias #define arr_clear(a) arr_free(a) -// add an item to the array - if allocation fails, the array will be freed and set to NULL. -// (how this works: if we can successfully grow the array, increase the length and add the item.) +/// add an item to the array - if allocation fails, the array will be freed and set to NULL. +/// (how this works: if we can successfully grow the array, increase the length and add the item.) #define arr_add(a, x) do { if (((a) = arr_cast_typeof(a) arr_grow1_((a), sizeof *(a)))) ((a)[arr_hdr_(a)->len++] = (x)); } while (0) -// like arr_add, but instead of passing it the value, it returns a pointer to the value. returns NULL if allocation failed. -// the added item will be zero-initialized. +/// like arr_add, but instead of passing it the value, it returns a pointer to the value. returns NULL if allocation failed. +/// the added item will be zero-initialized. #define arr_addp(a) arr_cast_typeof(a) arr_add_ptr_((void **)&(a), sizeof *(a)) -// set the length of `a` to `n`, increasing the capacity if necessary. -// the newly-added elements are zero-initialized. #define arr_qsort(a, cmp) qsort((a), arr_len(a), sizeof *(a), (cmp)) #define arr_remove_last(a) do { assert(a); if (--arr_hdr_(a)->len == 0) arr_free(a); } while (0) #define arr_remove(a, i) (void)((a) = arr_remove_((a), sizeof *(a), (i))) @@ -234,15 +235,21 @@ static void *arr_copy_(const void *arr, size_t member_size) { #define arr_copy(a) arr_cast_typeof(a) arr_copy_((a), sizeof *(a)) #define arr_foreach_ptr_end(a, type, var, end) type *end = (a) + arr_len(a); \ for (type *var = (a); var != end; ++var) -// Iterate through each element of the array, setting var to a pointer to the element. -// You can't use this like, e.g.: -// if (something) -// arr_foreach_ptr(a, int, i); -// You'll get an error. You will need to use braces because it expands to multiple statements. -// (we need to name the end pointer something unique, which is why there's that arr__join thing -// we can't just declare it inside the for loop, because type could be something like char *.) +/// Iterate through each element of the array, setting `var` to a pointer to the element. +/// +/// You can't use this like, e.g.: +/// ``` +/// if (something) +/// arr_foreach_ptr(a, int, i) +/// thing(*i); +/// ``` +/// You'll get an error. You will need to use braces because it expands to multiple statements. +/// (we need to name the end pointer something unique, which is why there's that `arr__join` thing +/// we can't just declare it inside the for loop, because type could be something like `char *`.) #define arr_foreach_ptr(a, type, var) arr_foreach_ptr_end(a, type, var, arr__join(_foreach_end,__LINE__)) - +/// Reverse array. +/// +/// You need to pass in the type because we don't have `typeof` in C yet (coming in C23 supposedly!) #define arr_reverse(a, type) do { \ u64 _i, _len = arr_len(a); \ for (_i = 0; 2*_i < _len; ++_i) { \ @@ -255,9 +262,10 @@ static void *arr_copy_(const void *arr, size_t member_size) { } \ } while (0) -// Ensure that enough space is allocated for n elements. +/// Ensure that enough space is allocated for `n` elements. #define arr_reserve(a, n) arr_reserve_((void **)&(a), sizeof *(a), (n)) -// Similar to arr_reserve, but also sets the length of the array to n. +/// set the length of `a` to `n`, increasing the capacity if necessary. +/// the newly-added elements are zero-initialized. #define arr_set_len(a, n) arr_set_len_((void **)&(a), sizeof *(a), (n)) #ifndef NDEBUG @@ -1,6 +1,5 @@ /* FUTURE FEATURES: -- doxygen documentation for ted.h - manual.md - CSS highlighting - option for separate colors for read/write highlights @@ -25,6 +24,9 @@ FUTURE FEATURES: - config variables - bind key to multiple commands - plugins? + - TED_PLUGIN macro defined before including ted.h + this can remove struct definitions to guarantee forwards compatibility + - language dynamic registration - keyboard macros - ctrl+9/0 to inc/dec number would be useful here - with macros we can really test performance of buffer_insert_text_at_pos, etc. (which should ideally be fast) @@ -1,4 +1,5 @@ -// a bunch of OS-dependent functions +/// \file +/// a bunch of OS-dependent functions #ifndef OS_H_ #define OS_H_ @@ -22,45 +23,46 @@ typedef struct { char name[]; } FsDirectoryEntry; -// returns what kind of thing this is. +/// returns what kind of thing this is. FsType fs_path_type(const char *path); FsPermission fs_path_permission(const char *path); -// Does this file exist? Returns false for directories. +/// Does this file exist? Returns false for directories. bool fs_file_exists(const char *path); -// Returns a NULL-terminated array of the files/directories in this directory, or NULL if the directory does not exist/out of memory. -// When you're done with the entries, call fs_dir_entries_free (or call free on each entry, then on the whole array). -// NOTE: The files/directories aren't returned in any particular order! +/// Returns a NULL-terminated array of the files/directories in this directory, or NULL if the directory does not exist/out of memory. +/// When you're done with the entries, call fs_dir_entries_free (or call free on each entry, then on the whole array). +/// NOTE: The files/directories aren't returned in any particular order! FsDirectoryEntry **fs_list_directory(const char *dirname); -// Create the directory specified by `path` -// Returns: -// 1 if the directory was created successfully -// 0 if the directory already exists -// -1 if the path already exists, but it's not a directory, or if there's another error (e.g. don't have permission to create directory). +/// Create the directory specified by `path`\n +/// Returns:\n +/// 1 if the directory was created successfully\n +/// 0 if the directory already exists\n +/// -1 if the path already exists, but it's not a directory, or if there's another error (e.g. don't have permission to create directory).\n int fs_mkdir(const char *path); -// Puts the current working directory into buf, including a null-terminator, writing at most buflen bytes. -// Returns: -// 1 if the working directory was inserted into buf successfully -// 0 if buf is too short to hold the cwd -// -1 if we can't get the cwd for whatever reason. +// Puts the current working directory into buf, including a null-terminator, writing at most buflen bytes.\n +// Returns:\n +// 1 if the working directory was inserted into buf successfully\n +// 0 if buf is too short to hold the cwd\n +// -1 if we can't get the cwd for whatever reason.\n int os_get_cwd(char *buf, size_t buflen); -// Unlike ISO C rename() function, this will overwrite `newname` if it exists. -// Returns: -// >= 0 if successful -// < 0 on error +// Unlike ISO C rename() function, this will overwrite `newname` if it exists.\n +// Returns:\n +// >= 0 if successful\n +// < 0 on error\n int os_rename_overwrite(const char *oldname, const char *newname); struct timespec time_last_modified(const char *filename); struct timespec time_get(void); -// sleep for a certain number of nanoseconds +/// sleep for a certain number of nanoseconds void time_sleep_ns(u64 ns); -// free the entries generated by fs_list_directory. +/// free the entries generated by fs_list_directory. static void fs_dir_entries_free(FsDirectoryEntry **entries) { for (int i = 0; entries[i]; ++i) free(entries[i]); free(entries); } +/// get current time in seconds since some arbitrary point static double time_get_seconds(void) { struct timespec t = time_get(); return (double)t.tv_sec @@ -69,17 +71,17 @@ static double time_get_seconds(void) { -// sleep for microseconds +/// sleep for microseconds static void time_sleep_us(u64 us) { time_sleep_ns(us * 1000); } -// sleep for milliseconds +/// sleep for milliseconds static void time_sleep_ms(u64 ms) { time_sleep_ns(ms * 1000000); } -// sleep for seconds +/// sleep for seconds static void time_sleep_s(u64 s) { time_sleep_ns(s * 1000000000); } @@ -87,60 +89,70 @@ static void time_sleep_s(u64 s) { typedef struct Process Process; -// zero everything except what you're using +/// zero everything except what you're using typedef struct { bool separate_stderr; const char *working_directory; + /// for forwards compatibility + char _reserved[256]; } ProcessSettings; typedef struct { - // string like "exited with code 9" + /// string like "exited with code 9" char message[62]; - // it might be possible that both signalled and exited are false, - // if something weird happens. + /// it might be possible that both `signalled` and `exited` are false, + /// if something weird happens. bool signalled; bool exited; + /// only relevant if `exited = true` int exit_code; + /// only relevant if `signalled = true` int signal; } ProcessExitInfo; -// get process ID of this process +/// get process ID of this process int process_get_id(void); -// execute the given command (like if it was passed to system()), creating a new Process object. -// returns a valid process object on failure, but it will have an error, according to process_geterr +/// execute the given command (like if it was passed to `system()`), creating a new \ref Process object. +/// +/// returns a valid process object on failure, but it will have an error, according to \ref process_geterr Process *process_run_ex(const char *command, const ProcessSettings *settings); -// like process_run_ex, but with the default settings +/// like \ref process_run_ex, but with the default settings Process *process_run(const char *command); -// returns the error last error produced, or NULL if there was no error. +/// returns the error last error produced, or NULL if there was no error. const char *process_geterr(Process *process); -// write to stdin -// returns: -// -2 on error -// or a non-negative number indicating the number of bytes written. -// Currently, this does a blocking write. +/// write to stdin +/// +/// returns -2 on error, +/// or a non-negative number indicating the number of bytes written. +/// Currently, this does a blocking write. long long process_write(Process *process, const char *data, size_t size); -// read from stdout+stderr -// returns: -// -2 on error -// -1 if no data is available right now -// 0 on end of file -// or a positive number indicating the number of bytes read to data (at most size) -// This does a nonblocking read. +/// read from stdout+stderr. +/// +/// returns:\n +/// -2 on error\n +/// -1 if no data is available right now\n +/// 0 on end of file\n +/// or a positive number indicating the number of bytes read to data (at most size)\n +/// This does a nonblocking read. long long process_read(Process *process, char *data, size_t size); -// like process_read, but reads stderr. -// this function ALWAYS RETURNS -2 if separate_stderr is not specified in the ProcessSettings. -// if separate_stderr is false, then both stdout and stderr will be sent via process_read. +/// like \ref process_read, but reads stderr. +/// +/// this function ALWAYS RETURNS -2 if `separate_stderr` is not specified in the \ref ProcessSettings. +/// if `separate_stderr` is false, then both stdout and stderr will be sent via \ref process_read. long long process_read_stderr(Process *process, char *data, size_t size); -// Checks if the process has exited. Returns: -// -1 if the process returned a non-zero exit code, or got a signal. -// 1 if the process exited successfully -// 0 if the process hasn't exited. -// If the process has exited, *info will be filled out with details. -// if the process is no longer running, *process will be freed and set to NULL. +/// Checks if the process has exited. +/// +/// Returns:\n +/// -1 if the process returned a non-zero exit code, or got a signal.\n +/// 1 if the process exited successfully\n +/// 0 if the process hasn't exited.\n +/// If the process has exited, `*info` will be filled out with details. +/// if the process is no longer running, `*process` will be freed and set to NULL. int process_check_status(Process **process, ProcessExitInfo *info); -// kills process if still running -// this also frees any resources used by `*process`. -// *process will be set to NULL. +/// kills process if still running +/// +/// this also frees any resources used by `*process`. +/// `*process` will be set to NULL. void process_kill(Process **process); #endif // OS_H_ @@ -1,9 +1,20 @@ -// the main header file for ted. -// this contains almost all of the function declarations. +/// \file +/// the main header file for ted. +/// +/// this contains almost all of the function declarations. + + +/// \mainpage ted doxygen documentation +/// +/// See "files" above. You probably want to look at \ref ted.h. #ifndef TED_H_ #define TED_H_ +#ifdef __cplusplus +extern "C" { +#endif + #include "base.h" #include "util.h" #include "os.h" @@ -16,20 +27,27 @@ #include "lib/glcorearb.h" #include "sdl-inc.h" +/// Version number #define TED_VERSION "2.0" +/// Version string #define TED_VERSION_FULL "ted v. " TED_VERSION -#define TED_PATH_MAX 256 -#define TED_CFG "ted.cfg" // config filename +/// Maximum path size ted handles. +#define TED_PATH_MAX 1024 +/// Config filename +#define TED_CFG "ted.cfg" +/// Minimum text size #define TEXT_SIZE_MIN 6 +/// Maximum text size #define TEXT_SIZE_MAX 70 -// max number of LSPs running at once +/// max number of LSPs running at once #define TED_LSP_MAX 200 -typedef u8 SyntaxState; +/// Current state of syntax highlighting. +typedef u32 SyntaxState; -// types of syntax highlighting -ENUM_U8 { +/// types of syntax highlighting +enum SyntaxCharType { SYNTAX_NORMAL, SYNTAX_KEYWORD, SYNTAX_BUILTIN, @@ -38,59 +56,76 @@ ENUM_U8 { SYNTAX_STRING, SYNTAX_CHARACTER, SYNTAX_CONSTANT, -} ENUM_U8_END(SyntaxCharType); +}; +/// Type of syntax highlighting. +typedef u8 SyntaxCharType; -#define SYNTAX_MATH SYNTAX_STRING // for tex -#define SYNTAX_CODE SYNTAX_PREPROCESSOR // for markdown -#define SYNTAX_LINK SYNTAX_CONSTANT // for markdown +/// for tex +#define SYNTAX_MATH SYNTAX_STRING +/// for markdown +#define SYNTAX_CODE SYNTAX_PREPROCESSOR +/// for markdown +#define SYNTAX_LINK SYNTAX_CONSTANT -// special keycodes for mouse X1 & X2 buttons. +/// special keycodes for mouse X1 & X2 buttons. enum { KEYCODE_X1 = 1<<20, KEYCODE_X2 }; -// a "key combo" is some subset of {control, shift, alt} + some key. +/// see \ref KEY_COMBO #define KEY_COMBO_COUNT (SCANCODE_COUNT << 3) -#define KEY_MODIFIER_CTRL_BIT 0 -#define KEY_MODIFIER_SHIFT_BIT 1 -#define KEY_MODIFIER_ALT_BIT 2 +/// see \ref KEY_COMBO +enum { + KEY_MODIFIER_CTRL_BIT, + KEY_MODIFIER_SHIFT_BIT, + KEY_MODIFIER_ALT_BIT +}; +/// see \ref KEY_COMBO #define KEY_MODIFIER_CTRL ((u32)1<<KEY_MODIFIER_CTRL_BIT) +/// see \ref KEY_COMBO #define KEY_MODIFIER_SHIFT ((u32)1<<KEY_MODIFIER_SHIFT_BIT) +/// see \ref KEY_COMBO #define KEY_MODIFIER_ALT ((u32)1<<KEY_MODIFIER_ALT_BIT) -// annoyingly SDL sets bit 30 for some keycodes +/// Create "key combo" from modifier and key. +/// +/// a "key combo" is some subset of {control, shift, alt} + some key. #define KEY_COMBO(modifier, key) ((u32)(modifier) \ | ((u32)(key >> 30) << 3)\ - | ((u32)(key) & ~(1u<<30)) << 4) + | ((u32)(key) & ~(1u<<30)) << 4) // annoyingly SDL sets bit 30 for some keycodes -// what happens when we press this key combo +/// Thing to do when a key combo is pressed. typedef struct { u32 key_combo; Command command; i64 argument; } KeyAction; -// a SettingsContext is a context where a specific set of settings are applied. -// this corresponds to [PATH//LANGUAGE.(section)] in config files +/// A SettingsContext is a context where a specific set of settings are applied. +/// this corresponds to `[PATH//LANGUAGE.(section)]` in config files. typedef struct { - Language language; // these settings apply to this language. - char *path; // these settings apply to all paths which start with this string, or all paths if path=NULL + /// The settings apply to this language. + Language language; + /// The settings apply to all paths which start with this string, or all paths if path=NULL + char *path; } SettingsContext; -// need to use reference counting for this because of Settings: -// We copy parent settings to children -// e.g. -// [core] -// bg-texture = "blablabla.png" -// [Javascript.core] -// some random shit -// the main Settings' bg_texture will get copied to javascript's Settings, -// so we need to be extra careful about when we delete textures. +/// Need to use reference counting for textures because of Settings: +/// We copy parent settings to children +/// e.g. +/// ``` +/// [core] +/// bg-texture = "blablabla.png" +/// [Javascript.core] +/// some random shit +/// ``` +/// the main Settings' bg_texture will get copied to javascript's Settings, +/// so we need to be extra careful about when we delete textures. typedef struct { u32 ref_count; GLuint texture; } GlRcTexture; -// reference-counted shader-array-buffer combo. +/// Reference-counted shader-array-buffer combo. typedef struct { u32 ref_count; GLuint shader; @@ -99,11 +134,11 @@ typedef struct { } GlRcSAB; -// all of ted's settings +/// All of ted's settings +/// +/// NOTE: to add more options to ted, add fields here, +/// and change the settings_<type> global constant near the top of config.c typedef struct { - // NOTE: to add more options to ted, add fields here, - // and change the settings_<type> global constant near the top of config.c - SettingsContext context; u32 colors[COLOR_COUNT]; float cursor_blink_time_on, cursor_blink_time_off; @@ -143,30 +178,36 @@ typedef struct { u8 tags_max_depth; GlRcSAB *bg_shader; GlRcTexture *bg_texture; + /// Comma-separated list of file names which identify the project root char root_identifiers[4096]; + /// LSP server command char lsp[512]; + /// LSP "configuration" JSON char lsp_configuration[4096]; + /// Build command. If non-empty, this overrides running `cargo build` if `Cargo.toml` exists, etc. char build_command[1024]; + /// Default build command for if `Cargo.toml`, `Makefile`, etc. do not exist. char build_default_command[1024]; - // [i] = comma-separated string of file extensions for language i, or NULL for none + /// `[i]` = comma-separated string of file extensions for language `i`, or `NULL` for none char *language_extensions[LANG_COUNT]; - KeyAction *key_actions; // dynamic array, sorted by KEY_COMBO(modifier, key) + /// dynamic array, sorted by KEY_COMBO(modifier, key) + KeyAction *key_actions; } Settings; -// a position in the buffer +/// A position in the buffer typedef struct { u32 line; u32 index; // index of character in line (not the same as column, since a tab is settings->tab_width columns) } BufferPos; -// a single line in a buffer +/// A single line in a buffer typedef struct { SyntaxState syntax; u32 len; char32_t *str; } Line; -// sections of ted.cfg +/// Sections of `ted.cfg` typedef enum { SECTION_NONE, SECTION_CORE, @@ -175,18 +216,20 @@ typedef enum { SECTION_EXTENSIONS } ConfigSection; -// this structure is used temporarily when loading settings -// it's needed because we want more specific contexts to be dealt with last. +/// This structure is used temporarily when loading settings +/// It's needed because we want more specific contexts to be dealt with last. typedef struct { - int index; // index in order of which part was read first. + /// index in order of which part was read first. + int index; SettingsContext context; ConfigSection section; char *file; u32 line; + /// contents of this config part char *text; } ConfigPart; -// this refers to replacing prev_len characters (found in prev_text) at pos with new_len characters +/// This refers to replacing prev_len characters (found in prev_text) at pos with new_len characters typedef struct { bool chain; // should this + the next edit be treated as one? BufferPos pos; @@ -196,132 +239,180 @@ typedef struct { double time; // time at start of edit (i.e. the time just before the edit), in seconds since epoch } BufferEdit; -// a buffer - this includes line buffers, unnamed buffers, the build buffer, etc. +/// A buffer - this includes line buffers, unnamed buffers, the build buffer, etc. typedef struct { - char *path; // NULL if this buffer is untitled or doesn't correspond to a file (e.g. line buffers) - struct Ted *ted; // we keep a back-pointer to the ted instance so we don't have to pass it in to every buffer function - double scroll_x, scroll_y; // number of characters scrolled in the x/y direction - double last_write_time; // last write time to `path`. - i16 manual_language; // 1 + the language the buffer has been manually set to, or 0 if it hasn't been manually set to anything + /// NULL if this buffer is untitled or doesn't correspond to a file (e.g. line buffers) + char *path; + /// we keep a back-pointer to the ted instance so we don't have to pass it in to every buffer function + struct Ted *ted; + /// number of characters scrolled in the x/y direction + double scroll_x, scroll_y; + /// last write time to `path` + double last_write_time; + /// 1 + the language the buffer has been manually set to, or 0 if it hasn't been manually set to anything + i16 manual_language; + /// position of cursor BufferPos cursor_pos; - BufferPos selection_pos; // if selection is true, the text between selection_pos and cursor_pos is selected. - bool is_line_buffer; // "line buffers" are buffers which can only have one line of text (used for inputs) - bool selection; // is anything selected? - bool store_undo_events; // set to false to disable undo events - // This is set to true whenever a change is made to the buffer, and never set to false by buffer_ functions. - // (Distinct from buffer_unsaved_changes) + /// if `selection` is true, the text between `selection_pos` and `cursor_pos` is selected. + BufferPos selection_pos; + /// "line buffers" are buffers which can only have one line of text (used for inputs) + bool is_line_buffer; + /// is anything selected? + bool selection; + /// set to false to disable undo events + bool store_undo_events; + /// This is set to true whenever a change is made to the buffer, and never set to false by buffer_ functions. + /// (Distinct from \ref buffer_unsaved_changes) bool modified; + /// will the next undo event be chained with the ones after? bool will_chain_edits; - bool chaining_edits; // are we chaining undo events together? + /// will the next undo event be chained with the previous one? + bool chaining_edits; + /// view-only mode bool view_only; - bool line_buffer_submitted; // (line buffers only) set to true when submitted. you have to reset it to false. - // If set to true, buffer will be scrolled to the cursor position next frame. - // This is to fix the problem that x1,y1,x2,y2 are not updated until the buffer is rendered. + /// (line buffers only) set to true when submitted. you have to reset it to false. + bool line_buffer_submitted; + /// If set to true, buffer will be scrolled to the cursor position next frame. + /// This is to fix the problem that x1,y1,x2,y2 are not updated until the buffer is rendered. bool center_cursor_next_frame; - float x1, y1, x2, y2; // buffer's rectangle on screen + /// buffer's rectangle on screen + float x1, y1, x2, y2; + /// number of lines in buffer u32 nlines; + /// capacity of `lines` u32 lines_capacity; - // which LSP this document is open in + /// which LSP this document is open in LSPID lsp_opened_in; - u32 undo_history_write_pos; // where in the undo history was the last write? used by buffer_unsaved_changes - u32 first_line_on_screen, last_line_on_screen; // which lines are on screen? updated when buffer_render is called. + /// where in the undo history was the last write? used by \ref buffer_unsaved_changes + u32 undo_history_write_pos; + /// which lines are on screen? updated when \ref buffer_render is called. + u32 first_line_on_screen, last_line_on_screen; // to cache syntax highlighting properly, it is important to keep track of the // first and last line modified since last frame. u32 frame_earliest_line_modified; + /// see \ref frame_earliest_line_modified. u32 frame_latest_line_modified; + /// lines Line *lines; + /// last error char error[256]; - BufferEdit *undo_history; // dynamic array of undo history - BufferEdit *redo_history; // dynamic array of redo history + /// dynamic array of undo history + BufferEdit *undo_history; + /// dynamic array of redo history + BufferEdit *redo_history; } TextBuffer; typedef enum { + /// No menu is open MENU_NONE, + /// "Open file" MENU_OPEN, + /// "Save file as" MENU_SAVE_AS, - MENU_WARN_UNSAVED, // warn about unsaved changes - MENU_ASK_RELOAD, // prompt about whether to reload file which has ben changed by another program + /// "X has unsaved changes" + MENU_WARN_UNSAVED, + /// "X has been changed by another program" + MENU_ASK_RELOAD, + /// "Go to definition of..." MENU_GOTO_DEFINITION, + /// "Go to line" MENU_GOTO_LINE, + /// "Command palette" MENU_COMMAND_SELECTOR, - MENU_SHELL, // run a shell command + /// "Run a shell command" + MENU_SHELL, } Menu; - -// an entry in a selector menu (e.g. the "open" menu) +/// an entry in a selector menu (e.g. the "open" menu) typedef struct { + /// label const char *name; - // if not NULL, this will show on the right side of the entry. + /// if not NULL, this will show on the right side of the entry. const char *detail; + /// color to draw text in u32 color; - // use this for whatever you want + /// use this for whatever you want u64 userdata; } SelectorEntry; -// a selector menu (e.g. the "open" menu) +/// a selector menu (e.g. the "open" menu) typedef struct { SelectorEntry *entries; u32 n_entries; Rect bounds; - u32 cursor; // index where the selector thing is + /// index where the selector thing is + u32 cursor; float scroll; - // whether or not we should let the user select entries using a cursor. + /// whether or not we should let the user select entries using a cursor. bool enable_cursor; } Selector; -// file entries for file selectors +/// file entries for file selectors typedef struct { - char *name; // just the file name - char *path; // full path + /// just the file name + char *name; + /// full path + char *path; FsType type; } FileEntry; -// a selector menu for files (e.g. the "open" menu) +/// a selector menu for files (e.g. the "open" menu) typedef struct { Selector sel; Rect bounds; u32 n_entries; FileEntry *entries; char cwd[TED_PATH_MAX]; - bool create_menu; // this is for creating files, not opening files + /// indicates that this is for creating files, not opening files + bool create_menu; } FileSelector; -// options for a pop-up menu +/// options for a pop-up menu typedef enum { POPUP_NONE, + /// "Yes" button POPUP_YES = 1<<1, + /// "No" button POPUP_NO = 1<<2, + /// "Cancel" button POPUP_CANCEL = 1<<3, } PopupOption; -// pop-up with "yes" and "no" buttons +/// pop-up with "yes" and "no" buttons #define POPUP_YES_NO (POPUP_YES | POPUP_NO) -// pop-up with "yes", "no", and "cancel" buttons +/// pop-up with "yes", "no", and "cancel" buttons #define POPUP_YES_NO_CANCEL (POPUP_YES | POPUP_NO | POPUP_CANCEL) -// a node is a collection of tabs OR a split of two nodes +/// A node is a collection of tabs OR a split of two nodes typedef struct { - u16 *tabs; // dynamic array of indices into ted->buffers, or NULL if this is a split - float split_pos; // number from 0 to 1 indicating where the split is. - u16 active_tab; // index of active tab in tabs. - bool split_vertical; // is the split vertical? if false, this split looks like a|b - u16 split_a; // split left/upper half; index into ted->nodes - u16 split_b; // split right/lower half + /// dynamic array of indices into ted->buffers, or `NULL` if this is a split + u16 *tabs; + /// number from 0 to 1 indicating where the split is. + float split_pos; + /// index of active tab in `tabs`. + u16 active_tab; + /// is the split vertical? if false, this split looks like a|b + bool split_vertical; + /// split left/upper half; index into `ted->nodes` + u16 split_a; + /// split right/lower half + u16 split_b; } Node; -// max number of buffers open at one time +/// max number of buffers open at one time #define TED_MAX_BUFFERS 256 -// max number of nodes open at one time +/// max number of nodes open at one time #define TED_MAX_NODES 256 -// max tabs per node +/// max tabs per node #define TED_MAX_TABS 100 -// max strings in all config files +/// max strings in all config files #define TED_MAX_STRINGS 1000 +/// "find" menu result typedef struct { BufferPos start; BufferPos end; @@ -330,10 +421,11 @@ typedef struct { typedef struct { char *path; BufferPos pos; - u32 build_output_line; // which line in the build output corresponds to this error + /// which line in the build output corresponds to this error + u32 build_output_line; } BuildError; -// LSPSymbolKinds are translated to these. this is a much coarser categorization +/// `LSPSymbolKind`s are translated to these. this is a much coarser categorization typedef enum { SYMBOL_OTHER, SYMBOL_FUNCTION, @@ -344,109 +436,121 @@ typedef enum { SYMBOL_KEYWORD } SymbolKind; -// a single autocompletion suggestion +/// a single autocompletion suggestion typedef struct { char *label; char *filter; char *text; - char *detail; // this can be NULL! - char *documentation; // this can be NULL! + /// this can be NULL! + char *detail; + /// this can be NULL! + char *documentation; bool deprecated; SymbolKind kind; } Autocompletion; enum { - // autocomplete/signature help was manually triggered + /// autocomplete/signature help was manually triggered TRIGGER_INVOKED = 0x12000, - // autocomplete list needs to be updated because more characters were typed + /// autocomplete list needs to be updated because more characters were typed TRIGGER_INCOMPLETE = 0x12001, - // signtaure help needs to be updated because the cursor was moved or - // the buffer's contents changed. + /// signtaure help needs to be updated because the cursor was moved or + /// the buffer's contents changed. TRIGGER_CONTENT_CHANGE = 0x12002, }; -// data needed for autocompletion +/// data needed for autocompletion typedef struct { - bool open; // is the autocomplete window open? - bool is_list_complete; // should the completions array be updated when more characters are typed? + /// is the autocomplete window open? + bool open; + /// should the completions array be updated when more characters are typed? + bool is_list_complete; - // what trigger caused the last request for completions: - // either a character code (for trigger characters), - // or one of the TRIGGER_* constants above + /// what trigger caused the last request for completions: + /// either a character code (for trigger characters), + /// or one of the `TRIGGER_*` constants above uint32_t trigger; LSPServerRequestID last_request; - // when we sent the request to the LSP for completions - // (this is used to figure out when we should display "Loading...") + /// when we sent the request to the LSP for completions + /// (this is used to figure out when we should display "Loading...") double last_request_time; - Autocompletion *completions; // dynamic array of all completions - u32 *suggested; // dynamic array of completions to be suggested (indices into completions) - BufferPos last_pos; // position of cursor last time completions were generated. if this changes, we need to recompute completions. - i32 cursor; // which completion is currently selected (index into suggested) + /// dynamic array of all completions + Autocompletion *completions; + /// dynamic array of completions to be suggested (indices into completions) + u32 *suggested; + /// position of cursor last time completions were generated. if this changes, we need to recompute completions. + BufferPos last_pos; + /// which completion is currently selected (index into suggested) + i32 cursor; i32 scroll; - // was the last request for phantom completion? + /// was the last request for phantom completion? bool last_request_phantom; - // current phantom completion to be displayed + /// current phantom completion to be displayed char *phantom; - - Rect rect; // rectangle where the autocomplete menu is (needed to avoid interpreting autocomplete clicks as other clicks) + /// rectangle where the autocomplete menu is (needed to avoid interpreting autocomplete clicks as other clicks) + Rect rect; } Autocomplete; -// data needed for finding usages +/// data needed for finding usages typedef struct { LSPServerRequestID last_request; double last_request_time; } Usages; -// a single signature in the signature help. +/// a single signature in the signature help. typedef struct { - // displayed normal + /// displayed normal char *label_pre; - // displayed bold + /// displayed bold char *label_active; - // displayed normal + /// displayed normal char *label_post; } Signature; -// max # of signatures to display at a time. +/// max number of signatures to display at a time. #define SIGNATURE_HELP_MAX 5 -// "signature help" (LSP) is thing that shows the current parameter, etc. +/// "signature help" (LSP) is thing that shows the current parameter, etc. typedef struct { LSPServerRequestID last_request; - // should we resend a signature help request this frame? + /// should we resend a signature help request this frame? bool retrigger; - // if signature_count = 0, signature help is closed + /// if signature_count = 0, signature help is closed u16 signature_count; Signature signatures[SIGNATURE_HELP_MAX]; } SignatureHelp; -// "hover" information from LSP server +/// "hover" information from LSP server typedef struct { LSPServerRequestID last_request; - // is some hover info being displayed? + /// is some hover info being displayed? bool open; - // text to display + /// text to display char *text; - // where the hover data is coming from. - // we use this to check if we need to refresh it. + /// where the hover data is coming from. + /// we use this to check if we need to refresh it. LSPDocumentPosition requested_position; + /// range in document to highlight LSPRange range; - double time; // how long the cursor has been hovering for + /// how long the cursor has been hovering for + double time; } Hover; -// symbol information for the definitions menu +/// symbol information for the definitions menu typedef struct { char *name; char *detail; u32 color; + /// is this from a LSP server (as opposed to ctags)? bool from_lsp; - LSPDocumentPosition position; // only set if from_lsp = true + /// only set if `from_lsp = true` + LSPDocumentPosition position; } SymbolInfo; -// determines which thing associated with a symbol to go to +/// determines which thing associated with a symbol to go to typedef enum { GOTO_DECLARATION, GOTO_DEFINITION, @@ -455,82 +559,108 @@ typedef enum { } GotoType; typedef struct { - // information about last LSP request sent LSPServerRequestID last_request; - double last_request_time; - - char *last_request_query; // last query string which we sent a request for - Selector selector; // for "go to definition of..." menu - SymbolInfo *all_definitions; // an array of all definitions (gotten from workspace/symbols) for "go to definition" menu + double last_request_time; + /// last query string which we sent a request for + char *last_request_query; + /// for "go to definition of..." menu + Selector selector; + /// an array of all definitions (gotten from workspace/symbols) for "go to definition" menu + SymbolInfo *all_definitions; } Definitions; -// "highlight" information from LSP server +/// "highlight" information from LSP server typedef struct { - LSPHighlight *highlights; LSPServerRequestID last_request; LSPDocumentPosition requested_position; + LSPHighlight *highlights; } Highlights; -// more severe message types should have higher numbers. -// they will override less severe messages. +/// more severe message types should have higher numbers. +/// they will override less severe messages. typedef enum { MESSAGE_INFO, MESSAGE_WARNING, MESSAGE_ERROR } MessageType; -// (almost) all data used by the ted application +/// (almost) all data used by the ted application typedef struct Ted { + /// all running LSP servers LSP *lsps[TED_LSP_MAX + 1]; - // current time (see time_get_seconds), as of the start of this frame + /// current time (see time_get_seconds), as of the start of this frame double frame_time; SDL_Window *window; Font *font_bold; Font *font; TextBuffer *active_buffer; - // buffer we are currently drag-to-selecting in, if any + /// buffer we are currently drag-to-selecting in, if any TextBuffer *drag_buffer; - // while a menu or something is open, there is no active buffer. when the menu is closed, - // the old active buffer needs to be restored. that's what this stores. + /// while a menu or something is open, there is no active buffer. when the menu is closed, + /// the old active buffer needs to be restored. that's what this stores. TextBuffer *prev_active_buffer; Node *active_node; - Settings *all_settings; // dynamic array of Settings. use Settings.context to figure out which one to use. - Settings *default_settings; // settings to use when no buffer is open + /// dynamic array of Settings. use Settings.context to figure out which one to use. + Settings *all_settings; + /// settings to use when no buffer is open + Settings *default_settings; float window_width, window_height; - u32 key_modifier; // which of shift, alt, ctrl are down right now. + /// which of shift, alt, ctrl are down right now. + u32 key_modifier; vec2 mouse_pos; u32 mouse_state; - u8 nmouse_clicks[4]; // nmouse_clicks[i] = length of mouse_clicks[i] - vec2 mouse_clicks[4][32]; // mouse_clicks[SDL_BUTTON_RIGHT], for example, is all the right mouse-clicks that have happened this frame - // number of times mouse was clicked at each position + /// `nmouse_clicks[i]` = length of `mouse_clicks[i]` + u8 nmouse_clicks[4]; + /// `mouse_clicks[SDL_BUTTON_RIGHT]`, for example, is all the right mouse-clicks that have happened this frame + vec2 mouse_clicks[4][32]; + /// number of times mouse was clicked at each position u8 mouse_click_times[4][32]; u8 nmouse_releases[4]; vec2 mouse_releases[4][32]; - int scroll_total_x, scroll_total_y; // total amount scrolled in the x and y direction this frame - Menu menu; // currently open menu, or MENU_NONE if no menu is open. + /// total amount scrolled this frame + int scroll_total_x, scroll_total_y; + /// currently open menu, or \ref MENU_NONE if no menu is open. + Menu menu; FileSelector file_selector; Selector command_selector; - TextBuffer line_buffer; // general-purpose line buffer for inputs -- used for menus - TextBuffer find_buffer; // use for "find" term in find/find+replace - TextBuffer replace_buffer; // "replace" for find+replace - TextBuffer build_buffer; // buffer for build output (view only) - TextBuffer argument_buffer; // used for command selector - double cursor_error_time; // time which the cursor error animation started (cursor turns red, e.g. when there's no autocomplete suggestion) - bool search_start_cwd; // should start_cwd be searched for files? set to true if the executable isn't "installed" + /// general-purpose line buffer for inputs -- used for menus + TextBuffer line_buffer; + /// use for "find" term in find/find+replace + TextBuffer find_buffer; + /// "replace" for find+replace + TextBuffer replace_buffer; + /// buffer for build output (view only) + TextBuffer build_buffer; + /// used for command selector + TextBuffer argument_buffer; + /// time which the cursor error animation started (cursor turns red, e.g. when there's no autocomplete suggestion) + double cursor_error_time; + /// should start_cwd be searched for files? set to true if the executable isn't "installed" + bool search_start_cwd; + /// CWD `ted` was started in char start_cwd[TED_PATH_MAX]; - bool quit; // if set to true, the window will close next frame. NOTE: this doesn't check for unsaved changes!! - bool find; // is the find or find+replace menu open? - bool replace; // is the find+replace menu open? - bool find_regex, find_case_sensitive; // find options - u32 find_flags; // flags used last time search term was compiled + /// if set to true, the window will close next frame. NOTE: this doesn't check for unsaved changes!! + bool quit; + /// is the find or find+replace menu open? + bool find; + /// is the find+replace menu open? + bool replace; + /// find options + bool find_regex, find_case_sensitive; + /// flags used last time search term was compiled + u32 find_flags; struct pcre2_real_code_32 *find_code; struct pcre2_real_match_data_32 *find_match_data; FindResult *find_results; - bool find_invalid_pattern; // invalid regex? - Command warn_unsaved; // if non-zero, the user is trying to execute this command, but there are unsaved changes - bool build_shown; // are we showing the build output? - bool building; // is the build process running? + /// invalid regex? + bool find_invalid_pattern; + /// if non-zero, the user is trying to execute this command, but there are unsaved changes + Command warn_unsaved; + /// are we showing the build output? + bool build_shown; + /// is the build process running? + bool building; Autocomplete autocomplete; SignatureHelp signature_help; Hover hover; @@ -540,421 +670,444 @@ typedef struct Ted { FILE *log; - BuildError *build_errors; // dynamic array of build errors - u32 build_error; // build error we are currently "on" + /// dynamic array of build errors + BuildError *build_errors; + /// build error we are currently "on" + u32 build_error; - // used by menus to keep track of the scroll position so we can return to it. + /// used by menus to keep track of the scroll position so we can return to it. vec2d prev_active_buffer_scroll; SDL_Cursor *cursor_arrow, *cursor_ibeam, *cursor_wait, *cursor_resize_h, *cursor_resize_v, *cursor_hand, *cursor_move; - // which cursor to use this frame - // this should be set to one of the cursor_* members above, or NULL for no cursor + /// which cursor to use this frame + /// this should be set to one of the cursor_* members above, or NULL for no cursor SDL_Cursor *cursor; - // node containing tab user is dragging around, NULL if user is not dragging a tab + /// node containing tab user is dragging around, NULL if user is not dragging a tab Node *dragging_tab_node; - // index in dragging_tab_node->tabs + /// index in dragging_tab_node->tabs u16 dragging_tab_idx; - vec2 dragging_tab_origin; // where the tab is being dragged from (i.e. mouse pos at start of drag action) + /// where the tab is being dragged from (i.e. mouse pos at start of drag action) + vec2 dragging_tab_origin; - // if not NULL, points to the node whose split the user is currently resizing. + /// if not `NULL`, points to the node whose split the user is currently resizing. Node *resizing_split; - char **shell_history; // dynamic array of history of commands run with :shell (UTF-8) - u32 shell_history_pos; // for keeping track of where we are in the shell history. + /// dynamic array of history of commands run with :shell (UTF-8) + char **shell_history; + /// for keeping track of where we are in the shell history. + u32 shell_history_pos; // points to a selector if any is open, otherwise NULL. Selector *selector_open; - float build_output_height; // what % of the screen the build output takes up + /// what % of the screen the build output takes up + float build_output_height; bool resizing_build_output; - double last_save_time; // last time a save command was executed. used for bg-shaders. + /// last time a save command was executed. used for bg-shaders. + double last_save_time; Process *build_process; - // When we read the stdout from the build process, the tail end of the read could be an - // incomplete UTF-8 code point. This is where we store that "tail end" until more - // data is available. (This is up to 3 bytes, null terminated) + /// When we read the stdout from the build process, the tail end of the read could be an + /// incomplete UTF-8 code point. This is where we store that "tail end" until more + /// data is available. (This is up to 3 bytes, null terminated) char build_incomplete_codepoint[4]; - char **build_queue; // allows execution of multiple commands -- needed for tags generation - char warn_unsaved_names[TED_PATH_MAX]; // comma-separated list of files with unsaved changes (only applicable if warn_unsaved != 0) - char warn_overwrite[TED_PATH_MAX]; // file name user is trying to overwrite - char ask_reload[TED_PATH_MAX]; // file name which we want to reload + /// allows execution of multiple commands -- needed for tags generation + char **build_queue; + /// comma-separated list of files with unsaved changes (only applicable if warn_unsaved != 0) + char warn_unsaved_names[TED_PATH_MAX]; + /// file name user is trying to overwrite + char warn_overwrite[TED_PATH_MAX]; + /// file name which we want to reload + char ask_reload[TED_PATH_MAX]; char local_data_dir[TED_PATH_MAX]; char global_data_dir[TED_PATH_MAX]; + /// home directory char home[TED_PATH_MAX]; - char cwd[TED_PATH_MAX]; // current working directory - char build_dir[TED_PATH_MAX]; // directory where we run the build command - char tags_dir[TED_PATH_MAX]; // where we are reading tags from + /// current working directory + char cwd[TED_PATH_MAX]; + /// directory where we run the build command + char build_dir[TED_PATH_MAX]; + /// where we are reading tags from + char tags_dir[TED_PATH_MAX]; bool nodes_used[TED_MAX_NODES]; - // nodes[0] is always the "root node", if any buffers are open. + /// `nodes[0]` is always the "root node", if any buffers are open. Node nodes[TED_MAX_NODES]; - // NOTE: the buffer at index 0 is reserved as a "null buffer" and should not be used. + /// NOTE: the buffer at index 0 is reserved as a "null buffer" and should not be used. bool buffers_used[TED_MAX_BUFFERS]; TextBuffer buffers[TED_MAX_BUFFERS]; - // config file strings + /// number of config file strings u32 nstrings; + /// config file strings char *strings[TED_MAX_STRINGS]; char window_title[256]; - // little box used to display errors and info. - double message_time; // time message box was opened - MessageType message_type; + /// little box used to display errors and info. char message[512]; + /// time message box was opened + double message_time; + MessageType message_type; MessageType message_shown_type; char message_shown[512]; } Ted; // === buffer.c === +/// Does this buffer have an error? bool buffer_has_error(TextBuffer *buffer); +/// get buffer error const char *buffer_get_error(TextBuffer *buffer); +/// clear buffer error void buffer_clear_error(TextBuffer *buffer); -// clear undo and redo history +/// clear undo and redo history void buffer_clear_undo_redo(TextBuffer *buffer); -// is this buffer empty? +/// is this buffer empty? bool buffer_empty(TextBuffer *buffer); -// returns the buffer's filename (not full path), or "Untitled" if this buffer is untitled. +/// returns the buffer's filename (not full path), or "Untitled" if this buffer is untitled. const char *buffer_display_filename(TextBuffer *buffer); -// does this buffer contained a named file (i.e. not a line buffer, not the build buffer, not untitled) +/// does this buffer contained a named file (i.e. not a line buffer, not the build buffer, not untitled) bool buffer_is_named_file(TextBuffer *buffer); -// create a new empty buffer with no file name +/// create a new empty buffer with no file name void buffer_create(TextBuffer *buffer, Ted *ted); -// create a new empty line buffer +/// create a new empty line buffer void line_buffer_create(TextBuffer *buffer, Ted *ted); -// does this buffer have unsaved changes? +/// does this buffer have unsaved changes? bool buffer_unsaved_changes(TextBuffer *buffer); -// returns the character at position pos, or 0 if pos is invalid +/// returns the character at position pos, or 0 if pos is invalid char32_t buffer_char_at_pos(TextBuffer *buffer, BufferPos pos); -// returns the character before position pos, or 0 if pos is invalid or at the start of a line +/// returns the character before position pos, or 0 if pos is invalid or at the start of a line char32_t buffer_char_before_pos(TextBuffer *buffer, BufferPos pos); -// returns the character after position pos, or 0 if pos is invalid or at the end of a line +/// returns the character after position pos, or 0 if pos is invalid or at the end of a line char32_t buffer_char_after_pos(TextBuffer *buffer, BufferPos pos); -// returns the character to the left of the cursor, or 0 if the cursor at the start of the line. +/// returns the character to the left of the cursor, or 0 if the cursor at the start of the line. char32_t buffer_char_before_cursor(TextBuffer *buffer); -// returns the character to the right of the cursor, 0 if cursor is at end of line +/// returns the character to the right of the cursor, 0 if cursor is at end of line char32_t buffer_char_after_cursor(TextBuffer *buffer); -// buffer position of start of file +/// buffer position of start of file BufferPos buffer_pos_start_of_file(TextBuffer *buffer); -// buffer position of end of file +/// buffer position of end of file BufferPos buffer_pos_end_of_file(TextBuffer *buffer); -// ensures that `p` refers to a valid position, moving it if needed. +/// ensures that `p` refers to a valid position, moving it if needed. void buffer_pos_validate(TextBuffer *buffer, BufferPos *p); -// is this a valid buffer position? +/// is this a valid buffer position? bool buffer_pos_valid(TextBuffer *buffer, BufferPos p); Language buffer_language(TextBuffer *buffer); -// clip the rectangle so it's all inside the buffer. returns true if there's any rectangle left. +/// clip the rectangle so it's all inside the buffer. returns true if there's any rectangle left. bool buffer_clip_rect(TextBuffer *buffer, Rect *r); -// get LSP server which deals with this buffer +/// get LSP server which deals with this buffer LSP *buffer_lsp(TextBuffer *buffer); -// Get the settings used for this buffer. +/// Get the settings used for this buffer. Settings *buffer_settings(TextBuffer *buffer); -// Get tab width for this buffer +/// Get tab width for this buffer u8 buffer_tab_width(TextBuffer *buffer); -// Get whether or not to indent with spaces for this buffer. +/// Get whether or not to indent with spaces for this buffer. bool buffer_indent_with_spaces(TextBuffer *buffer); -// NOTE: this string will be invalidated when the line is edited!!! -// only use it briefly!! +/// NOTE: this string will be invalidated when the line is edited!!! +/// only use it briefly!! String32 buffer_get_line(TextBuffer *buffer, u32 line_number); -// get at most `nchars` characters starting from position `pos`. -// returns the number of characters actually available. -// you can pass NULL for text if you just want to know how many -// characters *could* be accessed before the end of the file. +/// get at most `nchars` characters starting from position `pos`. +/// returns the number of characters actually available. +/// you can pass NULL for text if you just want to know how many +/// characters *could* be accessed before the end of the file. size_t buffer_get_text_at_pos(TextBuffer *buffer, BufferPos pos, char32_t *text, size_t nchars); -// returns a UTF-32 string of at most `nchars` code points from `buffer` starting at `pos` -// the string should be passed to str32_free. +/// returns a UTF-32 string of at most `nchars` code points from `buffer` starting at `pos` +/// the string should be passed to str32_free. String32 buffer_get_str32_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t nchars); -// get UTF-8 string at position, up to `nchars` code points (NOT bytes). -// the resulting string should be freed. +/// get UTF-8 string at position, up to `nchars` code points (NOT bytes). +/// the resulting string should be freed. char *buffer_get_utf8_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t nchars); -// Puts a UTF-8 string containing the contents of the buffer into out. -// Returns the number of bytes, including a null terminator. -// To use this function, first pass NULL for out to get the number of bytes you need to allocate. +/// Puts a UTF-8 string containing the contents of the buffer into out. +/// Returns the number of bytes, including a null terminator. +/// To use this function, first pass NULL for out to get the number of bytes you need to allocate. size_t buffer_contents_utf8(TextBuffer *buffer, char *out); -// Returns a UTF-8 string containing the contents of `buffer`. -// The return value should be freed.. +/// Returns a UTF-8 string containing the contents of `buffer`. +/// The return value should be freed.. char *buffer_contents_utf8_alloc(TextBuffer *buffer); -// perform a series of checks to make sure the buffer doesn't have any invalid values +/// perform a series of checks to make sure the buffer doesn't have any invalid values void buffer_check_valid(TextBuffer *buffer); -// free all resources used by the buffer +/// free all resources used by the buffer void buffer_free(TextBuffer *buffer); -// clear buffer contents +/// clear buffer contents void buffer_clear(TextBuffer *buffer); -// returns the length of the `line_number`th line (0-indexed), -// or 0 if `line_number` is out of range. +/// returns the length of the `line_number`th line (0-indexed), +/// or 0 if `line_number` is out of range. u32 buffer_line_len(TextBuffer *buffer, u32 line_number); -// returns the number of lines of text in the buffer into *lines (if not NULL), -// and the number of columns of text, i.e. the number of columns in the longest line displayed, into *cols (if not NULL) +/// returns the number of lines of text in the buffer into *lines (if not NULL), +/// and the number of columns of text, i.e. the number of columns in the longest line displayed, into *cols (if not NULL) void buffer_text_dimensions(TextBuffer *buffer, u32 *lines, u32 *columns); -// returns the number of rows of text that can fit in the buffer +/// returns the number of rows of text that can fit in the buffer float buffer_display_lines(TextBuffer *buffer); -// returns the number of columns of text that can fit in the buffer +/// returns the number of columns of text that can fit in the buffer float buffer_display_cols(TextBuffer *buffer); void buffer_scroll(TextBuffer *buffer, double dx, double dy); -// returns the screen position of the character at the given position in the buffer. +/// returns the screen position of the character at the given position in the buffer. vec2 buffer_pos_to_pixels(TextBuffer *buffer, BufferPos pos); -// convert pixel coordinates to a position in the buffer, selecting the closest character. -// returns false if the position is not inside the buffer, but still sets *pos to the closest character. +/// convert pixel coordinates to a position in the buffer, selecting the closest character. +/// returns false if the position is not inside the buffer, but still sets *pos to the closest character. bool buffer_pixels_to_pos(TextBuffer *buffer, vec2 pixel_coords, BufferPos *pos); -// scroll to `pos`, scrolling as little as possible while maintaining scrolloff. +/// scroll to `pos`, scrolling as little as possible while maintaining scrolloff. void buffer_scroll_to_pos(TextBuffer *buffer, BufferPos pos); -// scroll in such a way that this position is in the center of the screen +/// scroll in such a way that this position is in the center of the screen void buffer_scroll_center_pos(TextBuffer *buffer, BufferPos pos); void buffer_scroll_to_cursor(TextBuffer *buffer); -// scroll so that the cursor is in the center of the buffer's rectangle. +/// scroll so that the cursor is in the center of the buffer's rectangle. void buffer_center_cursor(TextBuffer *buffer); -// returns the number of characters successfully moved by. +/// returns the number of characters successfully moved by. i64 buffer_pos_move_left(TextBuffer *buffer, BufferPos *pos, i64 by); -// returns the number of characters successfully moved by. +/// returns the number of characters successfully moved by. i64 buffer_pos_move_right(TextBuffer *buffer, BufferPos *pos, i64 by); -// returns the number of lines successfully moved by. +/// returns the number of lines successfully moved by. i64 buffer_pos_move_up(TextBuffer *buffer, BufferPos *pos, i64 by); -// returns the number of lines successfully moved by. +/// returns the number of lines successfully moved by. i64 buffer_pos_move_down(TextBuffer *buffer, BufferPos *pos, i64 by); void buffer_cursor_move_to_pos(TextBuffer *buffer, BufferPos pos); -// returns the number of characters successfully moved by. +/// returns the number of characters successfully moved by. i64 buffer_cursor_move_left(TextBuffer *buffer, i64 by); -// returns the number of characters successfully moved by. +/// returns the number of characters successfully moved by. i64 buffer_cursor_move_right(TextBuffer *buffer, i64 by); -// returns the number of lines successfully moved by. +/// returns the number of lines successfully moved by. i64 buffer_cursor_move_up(TextBuffer *buffer, i64 by); -// returns the number of lines successfully moved by. +/// returns the number of lines successfully moved by. i64 buffer_cursor_move_down(TextBuffer *buffer, i64 by); -// returns the number of blank lines successfully moved by. +/// returns the number of blank lines successfully moved by. i64 buffer_pos_move_up_blank_lines(TextBuffer *buffer, BufferPos *pos, i64 by); -// returns the number of blank lines successfully moved by. +/// returns the number of blank lines successfully moved by. i64 buffer_pos_move_down_blank_lines(TextBuffer *buffer, BufferPos *pos, i64 by); -// returns the number of blank lines successfully moved by. +/// returns the number of blank lines successfully moved by. i64 buffer_cursor_move_up_blank_lines(TextBuffer *buffer, i64 by); -// returns the number of blank lines successfully moved by. +/// returns the number of blank lines successfully moved by. i64 buffer_cursor_move_down_blank_lines(TextBuffer *buffer, i64 by); -// returns the number of words successfully moved by. +/// returns the number of words successfully moved by. i64 buffer_pos_move_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); -// returns the number of words successfully moved by. +/// returns the number of words successfully moved by. i64 buffer_pos_move_left_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); -// returns the number of words successfully moved by. +/// returns the number of words successfully moved by. i64 buffer_pos_move_right_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); -// returns the number of words successfully moved by. +/// returns the number of words successfully moved by. i64 buffer_cursor_move_left_words(TextBuffer *buffer, i64 nwords); -// returns the number of words successfully moved by. +/// returns the number of words successfully moved by. i64 buffer_cursor_move_right_words(TextBuffer *buffer, i64 nwords); -// Returns a string of word characters (see is32_word) around the position, -// or an empty string if neither of the characters to the left and right of the cursor are word characters. -// NOTE: The string is invalidated when the buffer is changed!!! -// The return value should NOT be freed. +/// Returns a string of word characters (see is32_word) around the position, +/// or an empty string if neither of the characters to the left and right of the cursor are word characters. +/// NOTE: The string is invalidated when the buffer is changed!!! +/// The return value should NOT be freed. String32 buffer_word_at_pos(TextBuffer *buffer, BufferPos pos); -// Get the word at the cursor. -// NOTE: The string is invalidated when the buffer is changed!!! -// The return value should NOT be freed. +/// Get the word at the cursor. +/// NOTE: The string is invalidated when the buffer is changed!!! +/// The return value should NOT be freed. String32 buffer_word_at_cursor(TextBuffer *buffer); -// Get a UTF-8 string consisting of the word at the cursor. -// The return value should be freed. +/// Get a UTF-8 string consisting of the word at the cursor. +/// The return value should be freed. char *buffer_word_at_cursor_utf8(TextBuffer *buffer); -// Buffer position corresponding to the start of line `line` (0-indexed). +/// Buffer position corresponding to the start of line `line` (0-indexed). BufferPos buffer_pos_start_of_line(TextBuffer *buffer, u32 line); -// Buffer position corresponding to the end of line `line` (0-indexed). +/// Buffer position corresponding to the end of line `line` (0-indexed). BufferPos buffer_pos_end_of_line(TextBuffer *buffer, u32 line); -// Move cursor to the start of the line, like the Home key does. +/// Move cursor to the start of the line, like the Home key does. void buffer_cursor_move_to_start_of_line(TextBuffer *buffer); -// Move cursor to the end of the line, like the End key does. +/// Move cursor to the end of the line, like the End key does. void buffer_cursor_move_to_end_of_line(TextBuffer *buffer); -// Move cursor to the start of the file, like Ctrl+Home does. +/// Move cursor to the start of the file, like Ctrl+Home does. void buffer_cursor_move_to_start_of_file(TextBuffer *buffer); -// Move cursor to the end of the file, like Ctrl+End does. +/// Move cursor to the end of the file, like Ctrl+End does. void buffer_cursor_move_to_end_of_file(TextBuffer *buffer); -// Get the LSPDocumentID corresponding to the file this buffer contains. -// The return value is only useful if buffer_lsp(buffer) != NULL. +/// Get the LSPDocumentID corresponding to the file this buffer contains. +/// The return value is only useful if buffer_lsp(buffer) != NULL. LSPDocumentID buffer_lsp_document_id(TextBuffer *buffer); -// Get LSPPosition corresponding to position in buffer. +/// Get LSPPosition corresponding to position in buffer. LSPPosition buffer_pos_to_lsp_position(TextBuffer *buffer, BufferPos pos); -// Get LSPDocumentPosition corresponding to position in buffer. +/// Get LSPDocumentPosition corresponding to position in buffer. LSPDocumentPosition buffer_pos_to_lsp_document_position(TextBuffer *buffer, BufferPos pos); -// Convert LSPPosition to BufferPos. +/// Convert LSPPosition to BufferPos. BufferPos buffer_pos_from_lsp(TextBuffer *buffer, LSPPosition lsp_pos); -// Get the cursor position as an LSPPosition. +/// Get the cursor position as an LSPPosition. LSPPosition buffer_cursor_pos_as_lsp_position(TextBuffer *buffer); -// Get the cursor position as an LSPDocumentPosition. +/// Get the cursor position as an LSPDocumentPosition. LSPDocumentPosition buffer_cursor_pos_as_lsp_document_position(TextBuffer *buffer); -// Put text at a position. All text insertion should eventually go through this function. +/// Put text at a position. All text insertion should eventually go through this function. BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32 str); -// Insert a single character at a position. +/// Insert a single character at a position. void buffer_insert_char_at_pos(TextBuffer *buffer, BufferPos pos, char32_t c); -// Set the selection to between `buffer->cursor_pos` and `pos`, -// and move the cursor to `pos`. +/// Set the selection to between `buffer->cursor_pos` and `pos`, +/// and move the cursor to `pos`. void buffer_select_to_pos(TextBuffer *buffer, BufferPos pos); -// Like shift+left, move cursor `nchars` chars to the left, selecting everything in between. +/// Like shift+left, move cursor `nchars` chars to the left, selecting everything in between. void buffer_select_left(TextBuffer *buffer, i64 nchars); -// Like shift+right, move cursor `nchars` chars to the right, selecting everything in between. +/// Like shift+right, move cursor `nchars` chars to the right, selecting everything in between. void buffer_select_right(TextBuffer *buffer, i64 nchars); -// Like shift+down, move cursor `nchars` lines down, selecting everything in between. +/// Like shift+down, move cursor `nchars` lines down, selecting everything in between. void buffer_select_down(TextBuffer *buffer, i64 nchars); -// Like shift+up, move cursor `nchars` lines up, selecting everything in between. +/// Like shift+up, move cursor `nchars` lines up, selecting everything in between. void buffer_select_up(TextBuffer *buffer, i64 nchars); -// Move the cursor `by` lines down, selecting everything in between. +/// Move the cursor `by` lines down, selecting everything in between. void buffer_select_down_blank_lines(TextBuffer *buffer, i64 by); -// Move the cursor `by` lines up, selecting everything in between. +/// Move the cursor `by` lines up, selecting everything in between. void buffer_select_up_blank_lines(TextBuffer *buffer, i64 by); -// Move the cursor `nwords` words left, selecting everything in between. +/// Move the cursor `nwords` words left, selecting everything in between. void buffer_select_left_words(TextBuffer *buffer, i64 nwords); -// Move the cursor `nwords` words right, selecting everything in between. +/// Move the cursor `nwords` words right, selecting everything in between. void buffer_select_right_words(TextBuffer *buffer, i64 nwords); -// Like Shift+Home, move cursor to start of line and select everything in between. +/// Like Shift+Home, move cursor to start of line and select everything in between. void buffer_select_to_start_of_line(TextBuffer *buffer); -// Like Shift+End, move cursor to end of line and select everything in between. +/// Like Shift+End, move cursor to end of line and select everything in between. void buffer_select_to_end_of_line(TextBuffer *buffer); -// Like Ctrl+Shift+Home, move cursor to start of file and select everything in between. +/// Like Ctrl+Shift+Home, move cursor to start of file and select everything in between. void buffer_select_to_start_of_file(TextBuffer *buffer); -// Like Ctrl+Shift+End, move cursor to end of file and select everything in between. +/// Like Ctrl+Shift+End, move cursor to end of file and select everything in between. void buffer_select_to_end_of_file(TextBuffer *buffer); -// select the word the cursor is inside of +/// select the word the cursor is inside of void buffer_select_word(TextBuffer *buffer); -// select the line the cursor is currently on +/// select the line the cursor is currently on void buffer_select_line(TextBuffer *buffer); -// select all of the buffer's contents +/// select all of the buffer's contents void buffer_select_all(TextBuffer *buffer); -// Remove current selection. +/// Remove current selection. void buffer_deselect(TextBuffer *buffer); -// Scroll up by `npages` pages +/// Scroll up by `npages` pages void buffer_page_up(TextBuffer *buffer, i64 npages); -// Scroll down by `npages` pages +/// Scroll down by `npages` pages void buffer_page_down(TextBuffer *buffer, i64 npages); -// Scroll up by `npages` pages, selecting everything in between +/// Scroll up by `npages` pages, selecting everything in between void buffer_select_page_up(TextBuffer *buffer, i64 npages); -// Scroll down by `npages` pages, selecting everything in between +/// Scroll down by `npages` pages, selecting everything in between void buffer_select_page_down(TextBuffer *buffer, i64 npages); -// Delete `nchars` characters starting from `pos`. -// All text deletion should eventually go through this function. +/// Delete `nchars` characters starting from `pos`. +/// All text deletion should eventually go through this function. void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars); -// Delete characters between the two positions. -// The order of `p1` and `p2` is irrelevant. +/// Delete characters between the two positions. +/// The order of `p1` and `p2` is irrelevant. i64 buffer_delete_chars_between(TextBuffer *buffer, BufferPos p1, BufferPos p2); -// Delete current selection. +/// Delete current selection. i64 buffer_delete_selection(TextBuffer *buffer); -// Insert UTF-32 text at the cursor, and move the cursor to the end of it. +/// Insert UTF-32 text at the cursor, and move the cursor to the end of it. void buffer_insert_text_at_cursor(TextBuffer *buffer, String32 str); -// Insert a single character at the cursor, and move the cursor past it. +/// Insert a single character at the cursor, and move the cursor past it. void buffer_insert_char_at_cursor(TextBuffer *buffer, char32_t c); -// Insert UTF-8 text at the cursor, and move the cursor to the end of it. +/// Insert UTF-8 text at the cursor, and move the cursor to the end of it. void buffer_insert_utf8_at_cursor(TextBuffer *buffer, const char *utf8); -// Insert a "tab" at the cursor position, and move the cursor past it. -// This inserts spaces if ted is configured to indent with spaces. +/// Insert a "tab" at the cursor position, and move the cursor past it. +/// This inserts spaces if ted is configured to indent with spaces. void buffer_insert_tab_at_cursor(TextBuffer *buffer); -// Insert a newline at the cursor position. -// If `buffer` is a line buffer, this "submits" the buffer. -// If not, this auto-indents the next line, and moves the cursor to it. +/// Insert a newline at the cursor position. +/// If `buffer` is a line buffer, this "submits" the buffer. +/// If not, this auto-indents the next line, and moves the cursor to it. void buffer_newline(TextBuffer *buffer); -// Delete `nchars` characters after the cursor. +/// Delete `nchars` characters after the cursor. void buffer_delete_chars_at_cursor(TextBuffer *buffer, i64 nchars); -// Delete `nchars` characters before *pos, and set *pos to just before the deleted characters. -// Returns the number of characters actually deleted. +/// Delete `nchars` characters before *pos, and set *pos to just before the deleted characters. +/// Returns the number of characters actually deleted. i64 buffer_backspace_at_pos(TextBuffer *buffer, BufferPos *pos, i64 nchars); -// Delete `nchars` characters before the cursor position, and set the cursor position accordingly. -// Returns the number of characters actually deleted. +/// Delete `nchars` characters before the cursor position, and set the cursor position accordingly. +/// Returns the number of characters actually deleted. i64 buffer_backspace_at_cursor(TextBuffer *buffer, i64 nchars); -// Delete `nwords` words after the position. +/// Delete `nwords` words after the position. void buffer_delete_words_at_pos(TextBuffer *buffer, BufferPos pos, i64 nwords); -// Delete `nwords` words after the cursor. +/// Delete `nwords` words after the cursor. void buffer_delete_words_at_cursor(TextBuffer *buffer, i64 nwords); -// Delete `nwords` words before *pos, and set *pos to just before the deleted words. -// Returns the number of words actually deleted. +/// Delete `nwords` words before *pos, and set *pos to just before the deleted words. +/// Returns the number of words actually deleted. void buffer_backspace_words_at_pos(TextBuffer *buffer, BufferPos *pos, i64 nwords); -// Delete `nwords` words before the cursor position, and set the cursor position accordingly. -// Returns the number of words actually deleted. +/// Delete `nwords` words before the cursor position, and set the cursor position accordingly. +/// Returns the number of words actually deleted. void buffer_backspace_words_at_cursor(TextBuffer *buffer, i64 nwords); -// Undo `ntimes` times +/// Undo `ntimes` times void buffer_undo(TextBuffer *buffer, i64 ntimes); -// Redo `ntimes` times +/// Redo `ntimes` times void buffer_redo(TextBuffer *buffer, i64 ntimes); -// Start a new "edit chain". Undoing once after an edit chain will undo everything in the chain. +/// Start a new "edit chain". Undoing once after an edit chain will undo everything in the chain. void buffer_start_edit_chain(TextBuffer *buffer); -// End the edit chain. +/// End the edit chain. void buffer_end_edit_chain(TextBuffer *buffer); -// Copy the current selection to the clipboard. +/// Copy the current selection to the clipboard. void buffer_copy(TextBuffer *buffer); -// Copy the current selection to the clipboard, and delete it. +/// Copy the current selection to the clipboard, and delete it. void buffer_cut(TextBuffer *buffer); -// Insert the clipboard contents at the cursor position. +/// Insert the clipboard contents at the cursor position. void buffer_paste(TextBuffer *buffer); -// Load the file `path`. If `path` is not an absolute path, -// this function will fail. +/// Load the file `path`. If `path` is not an absolute path, +/// this function will fail. bool buffer_load_file(TextBuffer *buffer, const char *path); -// Reloads the file loaded in the buffer. +/// Reloads the file loaded in the buffer. void buffer_reload(TextBuffer *buffer); -// has this buffer been changed by another program since last save? +/// has this buffer been changed by another program since last save? bool buffer_externally_changed(TextBuffer *buffer); -// Clear `buffer`, and set its path to `path`. -// if `path` is NULL, this will turn `buffer` into an untitled buffer. +/// Clear `buffer`, and set its path to `path`. +/// if `path` is NULL, this will turn `buffer` into an untitled buffer. void buffer_new_file(TextBuffer *buffer, const char *path); -// Save the buffer to its current filename. This will rewrite the entire file, -// even if there are no unsaved changes. +/// Save the buffer to its current filename. This will rewrite the entire file, +/// even if there are no unsaved changes. bool buffer_save(TextBuffer *buffer); -// save, but with a different path +/// save, but with a different path bool buffer_save_as(TextBuffer *buffer, const char *new_filename); -// index of first line that will be displayed on screen +/// index of first line that will be displayed on screen u32 buffer_first_rendered_line(TextBuffer *buffer); -// index of last line that will be displayed on screen +/// index of last line that will be displayed on screen u32 buffer_last_rendered_line(TextBuffer *buffer); -// go to the definition/declaration/etc of the word at the cursor. +/// go to the definition/declaration/etc of the word at the cursor. void buffer_goto_word_at_cursor(TextBuffer *buffer, GotoType type); -// process a mouse click. -// returns true if the event was consumed. +/// process a mouse click. +/// returns true if the event was consumed. bool buffer_handle_click(Ted *ted, TextBuffer *buffer, vec2 click, u8 times); -// render the buffer in the given rectangle +/// render the buffer in the given rectangle void buffer_render(TextBuffer *buffer, Rect r); -// indent the given lines +/// indent the given lines void buffer_indent_lines(TextBuffer *buffer, u32 first_line, u32 last_line); -// de-indent the given lines +/// de-indent the given lines void buffer_dedent_lines(TextBuffer *buffer, u32 first_line, u32 last_line); -// indent the selected lines +/// indent the selected lines void buffer_indent_selection(TextBuffer *buffer); -// de-indent the selected lines +/// de-indent the selected lines void buffer_dedent_selection(TextBuffer *buffer); -// indent the line the cursor is on +/// indent the line the cursor is on void buffer_indent_cursor_line(TextBuffer *buffer); -// de-indent the line the cursor is on +/// de-indent the line the cursor is on void buffer_dedent_cursor_line(TextBuffer *buffer); -// comment the lines from `first_line` to `last_line` +/// comment the lines from `first_line` to `last_line` void buffer_comment_lines(TextBuffer *buffer, u32 first_line, u32 last_line); -// uncomment the lines from `first_line` to `last_line` +/// uncomment the lines from `first_line` to `last_line` void buffer_uncomment_lines(TextBuffer *buffer, u32 first_line, u32 last_line); -// comment the lines from `first_line` to `last_line`, or uncomment them if they're all commented. +/// comment the lines from `first_line` to `last_line`, or uncomment them if they're all commented. void buffer_toggle_comment_lines(TextBuffer *buffer, u32 first_line, u32 last_line); -// comment the selected lines, or uncomment them if they're all commented +/// comment the selected lines, or uncomment them if they're all commented void buffer_toggle_comment_selection(TextBuffer *buffer); -// make sure to call gl_geometry_draw after this +/// make sure to call \ref gl_geometry_draw after this void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range); -// returns true if p1 and p2 are equal +/// returns true if `p1` and `p2` are equal bool buffer_pos_eq(BufferPos p1, BufferPos p2); - -// returns: -// -1 if p1 comes before p2 -// +1 if p1 comes after p2 -// 0 if p1 = p2 -// faster than buffer_pos_diff (constant time) +/// returns `-1` if `p1` comes before `p2` +/// +/// `+1` if `p1` comes after `p2` +/// +/// `0` if `p1` = `p2` +/// +/// faster than \ref buffer_pos_diff (constant time) int buffer_pos_cmp(BufferPos p1, BufferPos p2); +/// returns "`p2 - p1`", that is, the number of characters between `p1` and `p2`. +i64 buffer_pos_diff(TextBuffer *buffer, BufferPos p1, BufferPos p2); // === build.c === -// clear build errors and stop +/// clear build errors and stop void build_stop(Ted *ted); -// call before adding anything to the build queue +/// call before adding anything to the build queue void build_queue_start(Ted *ted); -// add a command to the build queue. call build_queue_start before this. +/// add a command to the build queue. call build_queue_start before this. void build_queue_command(Ted *ted, const char *command); -// call this after calling build_queue_start, build_queue_command. -// make sure you set ted->build_dir before running this! +/// call this after calling build_queue_start, build_queue_command. +/// make sure you set ted->build_dir before running this! void build_queue_finish(Ted *ted); -// set up the build output buffer. +/// set up the build output buffer. void build_setup_buffer(Ted *ted); -// run a single command in the build window. -// make sure you set ted->build_dir before running this! +/// run a single command in the build window. +/// make sure you set ted->build_dir before running this! void build_start_with_command(Ted *ted, const char *command); -// figure out which build command to run, and run it. +/// figure out which build command to run, and run it. void build_start(Ted *ted); -// go to next build error +/// go to next build error void build_next_error(Ted *ted); -// go to previous build error +/// go to previous build error void build_prev_error(Ted *ted); -// find build errors in build buffer. +/// find build errors in build buffer. void build_check_for_errors(Ted *ted); void build_frame(Ted *ted, float x1, float y1, float x2, float y2); @@ -963,12 +1116,12 @@ void color_init(void); ColorSetting color_setting_from_str(const char *str); const char *color_setting_to_str(ColorSetting s); Status color_from_str(const char *str, u32 *color); -// which color setting should be used for the given symbol kind. -// this is the color used in the autocomplete selector, for example. +/// which color setting should be used for the given symbol kind. +/// this is the color used in the autocomplete selector, for example. ColorSetting color_for_symbol_kind(SymbolKind kind); -// perform SRC_ALPHA, ONE_MINUS_SRC_ALPHA blending with `bg` and `fg`. +/// perform SRC_ALPHA, ONE_MINUS_SRC_ALPHA blending with `bg` and `fg`. u32 color_blend(u32 bg, u32 fg); -// multiply color's alpha value by `opacity`. +/// multiply color's alpha value by `opacity`. u32 color_apply_opacity(u32 color, float opacity); // === command.c === @@ -978,60 +1131,63 @@ const char *command_to_str(Command c); void command_execute(Ted *ted, Command c, i64 argument); // === config.c === -// first, we read all config files, then we parse them. -// this is because we want less specific settings (e.g. settings applied -// to all languages instead of one particular language) to be applied first, -// then more specific settings are based off of those. -// EXAMPLE: -// ---config file 1--- -// [Javascript.core] -// syntax-highlighting = off -// (inherits tab-width = 4) -// [CSS.core] -// tab-width = 2 (overrides tab-width = 4) -// ---config file 2--- -// [core] -// tab-width = 4 +/// first, we read all config files, then we parse them. +/// this is because we want less specific settings (e.g. settings applied +/// to all languages instead of one particular language) to be applied first, +/// then more specific settings are based off of those. +/// +/// EXAMPLE: +/// ``` +/// ---config file 1--- +/// [Javascript.core] +/// syntax-highlighting = off +/// (inherits tab-width = 4) +/// [CSS.core] +/// tab-width = 2 (overrides tab-width = 4) +/// ---config file 2--- +/// [core] +/// tab-width = 4 +/// ``` void config_read(Ted *ted, ConfigPart **pparts, const char *filename); void config_parse(Ted *ted, ConfigPart **pparts); void config_free(Ted *ted); -// returns the best guess for the root directory of the project containing `path` -// (which should be an absolute path). -// the return value should be freed. +/// returns the best guess for the root directory of the project containing `path` +/// (which should be an absolute path). +/// the return value should be freed. char *settings_get_root_dir(Settings *settings, const char *path); -// how well does this settings context fit the given path and language? -// the context with the highest score will be chosen. +/// how well does this settings context fit the given path and language? +/// the context with the highest score will be chosen. long context_score(const char *path, Language lang, const SettingsContext *context); // === find.c === -// which buffer will be searched? +/// which buffer will be searched? TextBuffer *find_search_buffer(Ted *ted); -// height of the find/find+replace menu in pixels +/// height of the find/find+replace menu in pixels float find_menu_height(Ted *ted); -// update find results. -// if `force` is true, the results will be updated even if the pattern & flags have not been changed. +/// update find results. +/// if `force` is true, the results will be updated even if the pattern & flags have not been changed. void find_update(Ted *ted, bool force); -// replace the match we are currently highlighting, or do nothing if there is no highlighted match +/// replace the match we are currently highlighting, or do nothing if there is no highlighted match void find_replace(Ted *ted); -// go to next find result +/// go to next find result void find_next(Ted *ted); -// go to previous find result +/// go to previous find result void find_prev(Ted *ted); -// replace all matches +/// replace all matches void find_replace_all(Ted *ted); void find_menu_frame(Ted *ted, Rect menu_bounds); -// open the find/find+replace menu. +/// open the find/find+replace menu. void find_open(Ted *ted, bool replace); -// close the find/find+replace menu. +/// close the find/find+replace menu. void find_close(Ted *ted); // === gl.c === -// set by main() +/// set by main() extern float gl_window_width, gl_window_height; -// set by main() +/// set by main() extern int gl_version_major, gl_version_minor; -// macro trickery to avoid having to write everything multiple times +/// macro trickery to avoid having to write every GL function multiple times #define gl_for_each_proc(do)\ do(DRAWARRAYS, DrawArrays)\ do(GENTEXTURES, GenTextures)\ @@ -1092,74 +1248,74 @@ extern int gl_version_major, gl_version_minor; gl_for_each_proc(gl_declare_proc) #undef gl_declare_proc -// get addresses of GL functions +/// get addresses of GL functions void gl_get_procs(void); -// create a new reference-counted shader-array-buffer object. +/// create a new reference-counted shader-array-buffer object. GlRcSAB *gl_rc_sab_new(GLuint shader, GLuint array, GLuint buffer); -// increase reference count on `s`. +/// increase reference count on `s`. void gl_rc_sab_incref(GlRcSAB *s); -// decrease reference count on `*ps`, and set `*ps` to NULL if the reference count is 0. +/// decrease reference count on `*ps`, and set `*ps` to NULL if the reference count is 0. void gl_rc_sab_decref(GlRcSAB **ps); -// create a new reference-counted texture. +/// create a new reference-counted texture. GlRcTexture *gl_rc_texture_new(GLuint texture); -// increase reference count on `t`. +/// increase reference count on `t`. void gl_rc_texture_incref(GlRcTexture *t); -// decrease reference count on `*t`, and set `*t` to NULL if the reference count is 0. +/// decrease reference count on `*t`, and set `*t` to NULL if the reference count is 0. void gl_rc_texture_decref(GlRcTexture **pt); -// create and compile a shader +/// create and compile a shader GLuint gl_compile_shader(char error_buf[256], const char *code, GLenum shader_type); -// create new shader program from shaders +/// create new shader program from shaders GLuint gl_link_program(char error_buf[256], GLuint *shaders, size_t count); -// create a shader program from vertex shader and fragment shader source +/// create a shader program from vertex shader and fragment shader source GLuint gl_compile_and_link_shaders(char error_buf[256], const char *vshader_code, const char *fshader_code); -// prints a debug message if `attrib` is not found +/// prints a debug message if `attrib` is not found GLuint gl_attrib_location(GLuint program, const char *attrib); -// prints a debug message if `uniform` is not found +/// prints a debug message if `uniform` is not found GLint gl_uniform_location(GLuint program, const char *uniform); -// initialize geometry stuff +/// initialize geometry stuff void gl_geometry_init(void); -// queue a filled rectangle with the given color. +/// queue a filled rectangle with the given color. void gl_geometry_rect(Rect r, u32 color_rgba); -// queue the border of a rectangle with the given color. +/// queue the border of a rectangle with the given color. void gl_geometry_rect_border(Rect r, float border_thickness, u32 color); -// draw all queued geometry +/// draw all queued geometry void gl_geometry_draw(void); -// create an OpenGL texture object from an image file. +/// create an OpenGL texture object from an image file. GLuint gl_load_texture_from_image(const char *path); // === ide-autocomplete.c === -// open autocomplete -// trigger should either be a character (e.g. '.') or one of the TRIGGER_* constants. +/// open autocomplete +/// trigger should either be a character (e.g. '.') or one of the TRIGGER_* constants. void autocomplete_open(Ted *ted, uint32_t trigger); void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *response); -// select the completion the cursor is on, -// or select the phantom completion if there is one. +/// select the completion the cursor is on, +/// or select the phantom completion if there is one. void autocomplete_select_completion(Ted *ted); -// scroll completion list +/// scroll completion list void autocomplete_scroll(Ted *ted, i32 by); -// move cursor to next completion +/// move cursor to next completion void autocomplete_next(Ted *ted); -// move cursor to previous completion +/// move cursor to previous completion void autocomplete_prev(Ted *ted); -// close completion menu +/// close completion menu void autocomplete_close(Ted *ted); void autocomplete_frame(Ted *ted); // === ide-definitions.c === -// go to the definition of `name`. -// if `lsp` is NULL, tags will be used. -// Note: the document position is required for LSP requests because of overloading (where the name -// alone isn't sufficient) +/// go to the definition of `name`. +/// if `lsp` is NULL, tags will be used. +/// Note: the document position is required for LSP requests because of overloading (where the name +/// alone isn't sufficient) void definition_goto(Ted *ted, LSP *lsp, const char *name, LSPDocumentPosition pos, GotoType type); -// cancel the last go-to-definition / find symbols request. +/// cancel the last go-to-definition / find symbols request. void definition_cancel_lookup(Ted *ted); void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *response); -// open the definitions menu +/// open the definitions menu void definitions_selector_open(Ted *ted); -// update the definitions menu +/// update the definitions menu void definitions_selector_update(Ted *ted); void definitions_selector_render(Ted *ted, Rect bounds); -// close the definitions menu +/// close the definitions menu void definitions_selector_close(Ted *ted); void definitions_frame(Ted *ted); @@ -1174,10 +1330,10 @@ void hover_process_lsp_response(Ted *ted, LSPResponse *response); void hover_frame(Ted *ted, double dt); // === ide-signature-help.c === -// figure out new signature help +/// figure out new signature help void signature_help_retrigger(Ted *ted); -// open signature help. `trigger` should either be the trigger character (e.g. ',') -// or one of the TRIGGER_* constants. +/// open signature help. `trigger` should either be the trigger character (e.g. ',') +/// or one of the TRIGGER_* constants. void signature_help_open(Ted *ted, uint32_t trigger); bool signature_help_is_open(Ted *ted); void signature_help_close(Ted *ted); @@ -1185,9 +1341,9 @@ void signature_help_process_lsp_response(Ted *ted, const LSPResponse *response); void signature_help_frame(Ted *ted); // === ide-usages.c === -// cancel the last "find usages" request +/// cancel the last "find usages" request void usages_cancel_lookup(Ted *ted); -// find usages for word under the cursor in the active buffer. +/// find usages for word under the cursor in the active buffer. void usages_find(Ted *ted); void usages_process_lsp_response(Ted *ted, const LSPResponse *response); void usages_frame(Ted *ted); @@ -1195,49 +1351,49 @@ void usages_frame(Ted *ted); // === menu.c === void menu_close(Ted *ted); void menu_open(Ted *ted, Menu menu); -// process a :escape command (by default this happens when the escape key is pressed) +/// process a :escape command (by default this happens when the escape key is pressed) void menu_escape(Ted *ted); -// get width of menu in pixels +/// get width of menu in pixels float menu_get_width(Ted *ted); -// get rectangle which menu takes up +/// get rectangle which menu takes up Rect menu_rect(Ted *ted); void menu_update(Ted *ted); void menu_render(Ted *ted); -// move to next/previous command +/// move to next/previous command void menu_shell_move(Ted *ted, int direction); -// move to previous command +/// move to previous command void menu_shell_up(Ted *ted); -// move to next command +/// move to next command void menu_shell_down(Ted *ted); // === node.c === void node_switch_to_tab(Ted *ted, Node *node, u16 new_tab_index); -// go to the `n`th next tab (e.g. `n=1` goes to the next tab) -// going past the end of the tabs will "wrap around" to the first one. +/// go to the `n`th next tab (e.g. `n=1` goes to the next tab) +/// going past the end of the tabs will "wrap around" to the first one. void node_tab_next(Ted *ted, Node *node, i64 n); -// go to the `n`th previous tab (e.g. `n=1` goes to the previous tab) -// going before the first tab will "wrap around" to the last one. +/// go to the `n`th previous tab (e.g. `n=1` goes to the previous tab) +/// going before the first tab will "wrap around" to the last one. void node_tab_prev(Ted *ted, Node *node, i64 n); -// switch to a specific tab. if `tab` is out of range, nothing happens. +/// switch to a specific tab. if `tab` is out of range, nothing happens. void node_tab_switch(Ted *ted, Node *node, i64 tab); -// swap the position of two tabs +/// swap the position of two tabs void node_tabs_swap(Node *node, u16 tab1, u16 tab2); void node_free(Node *node); -// returns index of parent in ted->nodes, or -1 if this is the root node. +/// returns index of parent in ted->nodes, or -1 if this is the root node. i32 node_parent(Ted *ted, u16 node_idx); -// join this node with its sibling +/// join this node with its sibling void node_join(Ted *ted, Node *node); -// close a node, WITHOUT checking for unsaved changes +/// close a node, WITHOUT checking for unsaved changes void node_close(Ted *ted, u16 node_idx); -// close tab, WITHOUT checking for unsaved changes! -// returns true if the node is still open +/// close tab, WITHOUT checking for unsaved changes! +/// returns true if the node is still open bool node_tab_close(Ted *ted, Node *node, u16 index); void node_frame(Ted *ted, Node *node, Rect r); -// make a split +/// make a split void node_split(Ted *ted, Node *node, bool vertical); -// switch to the other side of the current split. +/// switch to the other side of the current split. void node_split_switch(Ted *ted); -// swap the two sides of the current split. +/// swap the two sides of the current split. void node_split_swap(Ted *ted); // === session.c === @@ -1247,169 +1403,174 @@ void session_read(Ted *ted); // === syntax.c === Language language_from_str(const char *str); const char *language_to_str(Language language); -// string which should be put before comments in the given language +/// string which should be put before comments in the given language const char *language_comment_start(Language l); -// string which should be put after comments in the given language +/// string which should be put after comments in the given language const char *language_comment_end(Language l); -// get the color setting associated with the given syntax highlighting type +/// get the color setting associated with the given syntax highlighting type ColorSetting syntax_char_type_to_color_setting(SyntaxCharType t); -// returns ')' for '(', etc., or 0 if c is not an opening bracket +/// returns ')' for '(', etc., or 0 if c is not an opening bracket char32_t syntax_matching_bracket(Language lang, char32_t c); -// returns true for opening brackets, false for closing brackets/non-brackets +/// returns true for opening brackets, false for closing brackets/non-brackets bool syntax_is_opening_bracket(Language lang, char32_t c); -// This is the main syntax highlighting function. It will determine which colors to use for each character. -// Rather than returning colors, it returns a character type (e.g. comment) which can be converted to a color. -// To highlight multiple lines, start out with a zeroed SyntaxState, and pass a pointer to it each time. -// You can set char_types to NULL if you just want to advance the state, and don't care about the character types. +/// This is the main syntax highlighting function. It will determine which colors to use for each character. +/// Rather than returning colors, it returns a character type (e.g. comment) which can be converted to a color. +/// To highlight multiple lines, start out with a zeroed SyntaxState, and pass a pointer to it each time. +/// You can set char_types to NULL if you just want to advance the state, and don't care about the character types. void syntax_highlight(SyntaxState *state, Language lang, const char32_t *line, u32 line_len, SyntaxCharType *char_types); // === tags.c === void tags_generate(Ted *ted, bool run_in_build_window); -// find all tags beginning with the given prefix, returning them into `*out`, writing at most out_size entries. -// you may pass NULL for `out`, in which case just the number of matching tags is returned -// (still maxing out at `out_size`). -// each element in `out` should be freed when you're done with them. +/// find all tags beginning with the given prefix, returning them into `*out`, writing at most out_size entries. +/// you may pass NULL for `out`, in which case just the number of matching tags is returned +/// (still maxing out at `out_size`). +/// each element in `out` should be freed when you're done with them. size_t tags_beginning_with(Ted *ted, const char *prefix, char **out, size_t out_size, bool error_if_tags_does_not_exist); -// go to the definition of the given tag +/// go to the definition of the given tag bool tag_goto(Ted *ted, const char *tag); -// get all tags in the tags file as SymbolInfos. +/// get all tags in the tags file as SymbolInfos. SymbolInfo *tags_get_symbols(Ted *ted); // === ted.c === -// for fatal errors +/// for fatal errors void die(PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2); -// display a message to the user +/// display a message to the user void ted_set_message(Ted *ted, MessageType type, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(3, 4); -// display an error to the user +/// display an error to the user void ted_error(Ted *ted, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); -// display a warning to the user +/// display a warning to the user void ted_warn(Ted *ted, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); -// display information to the user +/// display information to the user void ted_info(Ted *ted, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); -// for information that should be logged +/// for information that should be logged void ted_log(Ted *ted, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); -// set error to "out of memory" message. +/// set error to "out of memory" message. void ted_out_of_mem(Ted *ted); -// allocate memory, producing an error message and returning NULL on failure +/// allocate memory, producing an error message and returning NULL on failure void *ted_malloc(Ted *ted, size_t size); -// allocate memory, producing an error message and returning NULL on failure +/// allocate memory, producing an error message and returning NULL on failure void *ted_calloc(Ted *ted, size_t n, size_t size); -// allocate memory, producing an error message and returning NULL on failure +/// allocate memory, producing an error message and returning NULL on failure void *ted_realloc(Ted *ted, void *p, size_t new_size); -// Check the various places a ted data file could be -// (i.e. look for it in the local and global data directories), -// and return the full path. +/// Check the various places a ted data file could be +/// (i.e. look for it in the local and global data directories), +/// and return the full path. Status ted_get_file(Ted const *ted, const char *name, char *out, size_t outsz); -// get full path relative to ted->cwd. +/// get full path relative to ted->cwd. void ted_path_full(Ted *ted, const char *relpath, char *abspath, size_t abspath_size); -// set ted->active_buffer to something nice +/// set ted->active_buffer to something nice void ted_reset_active_buffer(Ted *ted); -// set ted's error message to the buffer's error. +/// set ted's error message to the buffer's error. void ted_error_from_buffer(Ted *ted, TextBuffer *buffer); -// Returns the buffer containing the file at `path`, or NULL if there is none. +/// Returns the buffer containing the file at `path`, or NULL if there is none. TextBuffer *ted_get_buffer_with_file(Ted *ted, const char *path); -// save all buffers +/// save all buffers bool ted_save_all(Ted *ted); -// reload all buffers from their files +/// reload all buffers from their files void ted_reload_all(Ted *ted); -// Load all the fonts ted will use. +/// Load all the fonts ted will use. void ted_load_fonts(Ted *ted); -// Get likely root directory of project containing `path`. -// The returned value should be freed. +/// Get likely root directory of project containing `path`. +/// The returned value should be freed. char *ted_get_root_dir_of(Ted *ted, const char *path); -// Get the root directory of the project containing the active buffer's file, -// or `ted->cwd` if no file is open. -// The returned value should be freed. +/// Get the root directory of the project containing the active buffer's file, +/// or `ted->cwd` if no file is open. +/// The returned value should be freed. char *ted_get_root_dir(Ted *ted); -// the settings of the active buffer, or the default settings if there is no active buffer +/// the settings of the active buffer, or the default settings if there is no active buffer Settings *ted_active_settings(Ted *ted); -// Get the settings for a file at the given path in the given language. +/// Get the settings for a file at the given path in the given language. Settings *ted_get_settings(Ted *ted, const char *path, Language language); -// Get LSP by ID. Returns NULL if there is no LSP with that ID. +/// Get LSP by ID. Returns NULL if there is no LSP with that ID. LSP *ted_get_lsp_by_id(Ted *ted, LSPID id); -// Get LSP which should be used for the given path and language. -// If no running LSP server would cover the path and language, a new one is -// started if possible. -// Returns NULL on failure (e.g. there is no LSP server -// specified for the given path and language). +/// Get LSP which should be used for the given path and language. +/// If no running LSP server would cover the path and language, a new one is +/// started if possible. +/// Returns NULL on failure (e.g. there is no LSP server +/// specified for the given path and language). LSP *ted_get_lsp(Ted *ted, const char *path, Language language); -// Get the LSP of the active buffer/ted->cwd. -// Returns NULL if there is no such server. +/// Get the LSP of the active buffer/ted->cwd. +/// Returns NULL if there is no such server. LSP *ted_active_lsp(Ted *ted); -// get the value of the given color setting, according to `ted_active_settings(ted)`. +/// get the value of the given color setting, according to `ted_active_settings(ted)`. u32 ted_active_color(Ted *ted, ColorSetting color); -// open the given file, or switch to it if it's already open. -// returns true on success. +/// open the given file, or switch to it if it's already open. +/// returns true on success. bool ted_open_file(Ted *ted, const char *filename); -// create a new buffer for the file `filename`, or open it if it's already open. -// if `filename` is NULL, this creates an untitled buffer. -// returns true on success. +/// create a new buffer for the file `filename`, or open it if it's already open. +/// if `filename` is NULL, this creates an untitled buffer. +/// returns true on success. bool ted_new_file(Ted *ted, const char *filename); -// returns the index of an available buffer, or -1 if none are available +/// returns the index of an available buffer, or -1 if none are available i32 ted_new_buffer(Ted *ted); -// Returns the index of an available node, or -1 if none are available +/// Returns the index of an available node, or -1 if none are available i32 ted_new_node(Ted *ted); -// Opposite of ted_new_buffer -// Make sure you set active_buffer to something else if you delete it! +/// Opposite of ted_new_buffer +/// Make sure you set active_buffer to something else if you delete it! void ted_delete_buffer(Ted *ted, u16 index); -// save all changes to all buffers with unsaved changes. +/// save all changes to all buffers with unsaved changes. bool ted_save_all(Ted *ted); -// sets the active buffer to this buffer, and updates active_node, etc. accordingly -// you can pass NULL to buffer to make it so no buffer is active. +/// sets the active buffer to this buffer, and updates active_node, etc. accordingly +/// you can pass NULL to buffer to make it so no buffer is active. void ted_switch_to_buffer(Ted *ted, TextBuffer *buffer); -// switch to this node +/// switch to this node void ted_node_switch(Ted *ted, Node *node); -// load ted.cfg files +/// load ted.cfg files void ted_load_configs(Ted *ted, bool reloading); -// handle a key press +/// handle a key press void ted_press_key(Ted *ted, SDL_Keycode keycode, SDL_Keymod modifier); -// get the buffer and buffer position where the mouse is. -// returns false if the mouse is not in a buffer. +/// get the buffer and buffer position where the mouse is. +/// returns false if the mouse is not in a buffer. Status ted_get_mouse_buffer_pos(Ted *ted, TextBuffer **pbuffer, BufferPos *ppos); -// make the cursor red for a bit to indicate an error (e.g. no autocompletions) +/// make the cursor red for a bit to indicate an error (e.g. no autocompletions) void ted_flash_error_cursor(Ted *ted); -// go to `path` at line `line` and index `index`, opening a new buffer if necessary. -// if `is_lsp` is set to true, `index` is interpreted as a UTF-16 offset rather than a UTF-32 offset. +/// go to `path` at line `line` and index `index`, opening a new buffer if necessary. +/// if `is_lsp` is set to true, `index` is interpreted as a UTF-16 offset rather than a UTF-32 offset. void ted_go_to_position(Ted *ted, const char *path, u32 line, u32 index, bool is_lsp); -// go to this LSP document position, opening a new buffer containing the file if necessary. +/// go to this LSP document position, opening a new buffer containing the file if necessary. void ted_go_to_lsp_document_position(Ted *ted, LSP *lsp, LSPDocumentPosition position); -// cancel this LSP request. also zeroes *request -// if *request is zeroed, this does nothing. +/// cancel this LSP request. also zeroes *request +/// if *request is zeroed, this does nothing. void ted_cancel_lsp_request(Ted *ted, LSPServerRequestID *request); -// how tall is a line buffer? +/// how tall is a line buffer? float ted_line_buffer_height(Ted *ted); -// check for orphaned nodes and node cycles +/// check for orphaned nodes and node cycles void ted_check_for_node_problems(Ted *ted); -// convert LSPWindowMessageType to MessageType +/// convert LSPWindowMessageType to MessageType MessageType ted_message_type_from_lsp(LSPWindowMessageType type); -// get colors to use for message box +/// get colors to use for message box void ted_color_settings_for_message_type(MessageType type, ColorSetting *bg_color, ColorSetting *border_color); // === ui.c === -// move selector cursor up by `n` entries +/// move selector cursor up by `n` entries void selector_up(Ted *ted, Selector *s, i64 n); -// move selector cursor down by `n` entries +/// move selector cursor down by `n` entries void selector_down(Ted *ted, Selector *s, i64 n); -// sort entries alphabetically +/// sort entries alphabetically void selector_sort_entries_by_name(Selector *s); -// returns a null-terminated UTF-8 string of the entry selected, or NULL if none was. -// also, sel->cursor will be set to the index of the entry, even if the mouse was used. -// you should call free() on the return value. +/// returns a null-terminated UTF-8 string of the entry selected, or NULL if none was. +/// also, sel->cursor will be set to the index of the entry, even if the mouse was used. +/// you should call free() on the return value. char *selector_update(Ted *ted, Selector *s); -// NOTE: also renders the line buffer +/// NOTE: also renders the line buffer void selector_render(Ted *ted, Selector *s); void file_selector_free(FileSelector *fs); -// returns the name of the selected file, or NULL if none was selected. -// the returned pointer should be freed. +/// returns the name of the selected file, or NULL if none was selected. +/// the returned pointer should be freed. char *file_selector_update(Ted *ted, FileSelector *fs); void file_selector_render(Ted *ted, FileSelector *fs); vec2 button_get_size(Ted *ted, const char *text); void button_render(Ted *ted, Rect button, const char *text, u32 color); -// returns true if the button was clicked on. +/// returns true if the button was clicked on. bool button_update(Ted *ted, Rect button); -// returns selected option, or POPUP_NONE if none was selected +/// returns selected option, or POPUP_NONE if none was selected PopupOption popup_update(Ted *ted, u32 options); void popup_render(Ted *ted, u32 options, const char *title, const char *body); vec2 checkbox_frame(Ted *ted, bool *value, const char *label, vec2 pos); + +#ifdef __cplusplus +} // extern "C" +#endif + #endif @@ -1,11 +1,16 @@ -// A text-rendering interface. -// Example usage: -// Font *font = text_font_load("font.ttf", 18); -// if (font) { -// text_utf8(font, "Hello", 5, 5, 0xFF0000FF); -// text_utf8(font, "Goodbye", 5, 100, 0x00FF00FF); -// text_render(font); -// } +/// \file +/// A text-rendering interface. +/// +/// Example usage: +/// +/// ``` +/// Font *font = text_font_load("font.ttf", 18); +/// if (font) { +/// text_utf8(font, "Hello", 5, 5, 0xFF0000FF); +/// text_utf8(font, "Goodbye", 5, 100, 0x00FF00FF); +/// text_render(font); +/// } +/// ``` #ifndef TEXT_H_ #define TEXT_H_ @@ -13,24 +18,34 @@ #include "base.h" #include "util.h" +/// a font typedef struct Font Font; +/// text render state. +/// +/// do not construct this directly instead use \ref text_render_state_default. typedef struct { - // should the text actually be rendered (set to false to get text size) + /// should the text actually be rendered (set to false to get text size) bool render; - bool wrap; // should the text wrap around to min_x when it reaches max_x? NOTE: this is character-by-character wrapping, not word wrap - + /// should the text wrap around to min_x when it reaches max_x? NOTE: this is character-by-character wrapping, not word wrap + bool wrap; + /// where to draw double x, y; - // points where the text should be cut off + /// points where the text should be cut off float min_x, max_x, min_y, max_y; - // [0] = r, [1] = g, [2] = b, [3] = a. + /// `[0] = r, [1] = g, [2] = b, [3] = a`. float color[4]; - // largest x & y achieved (for computing size) + /// largest x achieved (for computing size) double x_largest; + /// largest y achieved (for computing size) double y_largest; + + /// used for forwards-compatibility + char _reserved[64]; } TextRenderState; +/// text anchor typedef enum { ANCHOR_TOP_LEFT, ANCHOR_TOP_MIDDLE, @@ -43,38 +58,48 @@ typedef enum { ANCHOR_BOTTOM_RIGHT, } Anchor; +/// returns false on error. bool text_init(void); +/// is there error? bool text_has_err(void); -// Get the current error. Errors will NOT be overwritten with newer errors. +/// Get the current error. Errors will NOT be overwritten with newer errors. const char *text_get_err(void); -// Clear the current error. +/// Clear the current error. void text_clear_err(void); -// Load a TTF font found in ttf_filename with the given font size (character pixel height) +/// Load a TTF font found in ttf_filename with the given font size (character pixel height) Font *text_font_load(const char *ttf_filename, float font_size); -// Height of a character of this font in pixels. +/// Height of a character of this font in pixels. float text_font_char_height(Font *font); -// Width of the character 'a' of this font in pixels. -// This is meant to be only used for monospace fonts. +/// Width of the character 'a' of this font in pixels. +/// This is meant to be only used for monospace fonts. float text_font_char_width(Font *font); -// Force text to advance by text_font_char_width(font) pixels per character (actually, per code point). +/// Force text to advance by text_font_char_width(font) pixels per character (actually, per code point). void text_font_set_force_monospace(Font *font, bool force); -// Get the dimensions of some text. +/// Get the dimensions of some text. void text_get_size(Font *font, const char *text, float *width, float *height); +/// Get the dimensions of some text. vec2 text_get_size_vec2(Font *font, const char *text); +/// Get the dimensions of some text. void text_get_size32(Font *font, const char32_t *text, u64 len, float *width, float *height); +/// Draw some text. void text_utf8(Font *font, const char *text, double x, double y, u32 color); +/// Draw some text with an anchor. void text_utf8_anchored(Font *font, const char *text, double x, double y, u32 color, Anchor anchor); +/// Draw a single character. void text_char_with_state(Font *font, TextRenderState *state, char32_t c); +/// Draw some UTF-8 text with a \ref TextRenderState. void text_utf8_with_state(Font *font, TextRenderState *state, const char *str); -// Free memory used by font. +/// Free memory used by font. void text_font_free(Font *font); +/// Render all text drawn with \ref text_utf8, etc. void text_render(Font *font); - -// The "default" text rendering state - everything you need to just render text normally. -// This lets you do stuff like: -// TextRenderState state = text_render_state_default; -// (set a few options) -// text_render_with_state(font, &state, ...) +/// The "default" text rendering state - everything you need to just render text normally. +/// This lets you do stuff like: +/// ``` +/// TextRenderState state = text_render_state_default; +/// (set a few options) +/// text_render_with_state(font, &state, ...) +/// ``` extern const TextRenderState text_render_state_default; #endif @@ -1,10 +1,14 @@ -// functions for dealing with UTF-8/UTF-16/UTF-32. -// this file is entirely self-contained. +/// \file +/// functions for dealing with UTF-8/UTF-16/UTF-32. +/// +/// this file is entirely self-contained. #ifndef UNICODE_H_ #define UNICODE_H_ +/// useful for "this character couldn't be rendered / is invalid UTF-8" #define UNICODE_BOX_CHARACTER 0x2610 -#define UNICODE_CODE_POINTS 0x110000 // number of Unicode code points +/// number of Unicode code points +#define UNICODE_CODE_POINTS 0x110000 #include <stddef.h> #include <stdint.h> @@ -19,15 +23,16 @@ static bool unicode_is_continuation_byte(uint8_t byte) { return (byte & 0xC0) == 0x80; } -// A lot like mbrtoc32. Doesn't depend on the locale though, for one thing. -// *c will be filled with the next UTF-8 code point in `str`. `bytes` refers to the maximum -// number of bytes that can be read from `str` (note: this function will never read past a null -// byte, even if `bytes` indicates that it could). -// Returns: -// 0 - if a null character was encountered or if `bytes == 0` -// (size_t)-1 - on invalid UTF-8 -// (size_t)-2 - on incomplete code point (str should be longer) -// other - the number of bytes read from `str`. +/// A lot like mbrtoc32. Doesn't depend on the locale though, for one thing. +/// +/// *c will be filled with the next UTF-8 code point in `str`. `bytes` refers to the maximum +/// number of bytes that can be read from `str` (note: this function will never read past a null +/// byte, even if `bytes` indicates that it could). +/// Returns:\n +/// `0` - if a null character was encountered or if `bytes == 0`\n +/// `(size_t)-1` - on invalid UTF-8\n +/// `(size_t)-2` - on incomplete code point (str should be longer)\n +/// other - the number of bytes read from `str`. static size_t unicode_utf8_to_utf32(uint32_t *c, const char *str, size_t bytes) { *c = 0; if (bytes == 0) { @@ -121,10 +126,11 @@ static size_t unicode_utf8_to_utf32(uint32_t *c, const char *str, size_t bytes) } } -// A lot like c32rtomb -// Converts a UTF-32 codepoint to a UTF-8 string. Writes at most 4 bytes to s. -// NOTE: It is YOUR JOB to null-terminate your string if the UTF-32 isn't null-terminated! -// Returns the number of bytes written to s, or (size_t)-1 on invalid UTF-32. +/// A lot like c32rtomb +/// +/// Converts a UTF-32 codepoint to a UTF-8 string. Writes at most 4 bytes to s. +/// NOTE: It is YOUR JOB to null-terminate your string if the UTF-32 isn't null-terminated! +/// Returns the number of bytes written to `s`, or `(size_t)-1` on invalid UTF-32. static size_t unicode_utf32_to_utf8(char *s, uint32_t c32) { uint8_t *p = (uint8_t *)s; if (c32 <= 0x7F) { @@ -162,7 +168,8 @@ static size_t unicode_utf32_to_utf8(char *s, uint32_t c32) { // get the number of UTF-16 codepoints needed to encode `str`. -// returns (size_t)-1 on bad UTF-8 +/// +// returns `(size_t)-1` on bad UTF-8 static size_t unicode_utf16_len(const char *str) { size_t len = 0; uint32_t c = 0; @@ -179,9 +186,11 @@ static size_t unicode_utf16_len(const char *str) { return len; } -// returns the UTF-8 offset from `str` which corresponds to a UTF-16 offset of utf16_offset (rounds down if utf16_offset is in the middle of a codepoint). -// returns strlen(str) if utf16_offset == unicode_utf16_len(str) -// returns (size_t)-1 on bad UTF-8, or if utf16_offset > unicode_utf16_len(str) +/// returns the UTF-8 offset from `str` which corresponds to a UTF-16 offset of +/// `utf16_offset` (rounds down if `utf16_offset` is in the middle of a codepoint). +/// +/// returns `strlen(str)` if `utf16_offset == unicode_utf16_len(str)` +/// returns `(size_t)-1` on bad UTF-8, or if `utf16_offset > unicode_utf16_len(str)` static size_t unicode_utf16_to_utf8_offset(const char *str, size_t utf16_offset) { size_t offset = 0; uint32_t c = 0; @@ -1,15 +1,15 @@ -// C utility functions -// these utilities should be self-contained +/// \file +/// C utility functions #ifndef UTIL_H_ #define UTIL_H_ #include "base.h" -// like snprintf, but not screwed up on windows +/// like snprintf, but not screwed up on old versions of windows #define str_printf(str, size, ...) (str)[(size) - 1] = '\0', snprintf((str), (size) - 1, __VA_ARGS__) -// like snprintf, but the size is taken to be the length of the array str. -// first, check that str is actually an array +/// like snprintf, but the size is taken to be the length of the array str. +/// first, check that str is actually an array #define strbuf_printf(str, ...) assert(sizeof str != 4 && sizeof str != 8), \ str_printf(str, sizeof str, __VA_ARGS__) #define str_catf(str, size, ...) str_printf((str) + strlen(str), (size) - strlen(str), __VA_ARGS__) @@ -42,14 +42,14 @@ typedef struct { vec2 pos, size; } Rect; -// UTF-32 string +/// UTF-32 string typedef struct { char32_t *str; size_t len; } String32; -// ctype functions for 32-bit chars. +/// ctype functions for 32-bit chars. bool is32_word(char32_t c); bool is32_space(char32_t c); bool is32_alpha(char32_t c); @@ -57,75 +57,75 @@ bool is32_alnum(char32_t c); bool is32_digit(char32_t c); bool is32_graph(char32_t c); bool is_a_tty(FILE *out); -// terminal colors. if `out` is a TTY, these will return the appropriate escape sequences. -// if `out` is not a TTY, these will return "". +/// terminal colors. if `out` is a TTY, these will return the appropriate escape sequences. +/// if `out` is not a TTY, these will return "". const char *term_italics(FILE *out); const char *term_bold(FILE *out); const char *term_yellow(FILE *out); const char *term_clear(FILE *out); -// number of 1 bits in x. +/// number of 1 bits in x. u8 util_popcount(u64 x); -// count leading zeroes. if x == 0, this always returns 32 (not undefined behavior). +/// count leading zeroes. if x == 0, this always returns 32 (not undefined behavior). u8 util_count_leading_zeroes32(u32 x); -// is x a power of 2? +/// is x a power of 2? bool util_is_power_of_2(u64 x); -// like memchr, but 32-bit. +/// like memchr, but 32-bit. char32_t *util_mem32chr(char32_t *s, char32_t c, size_t n); -// like memchr, but 32-bit, and constant. +/// like memchr, but 32-bit, and constant. const char32_t *util_mem32chr_const(const char32_t *s, char32_t c, size_t n); -// does `str` have this prefix? +/// does `str` have this prefix? bool str_has_prefix(const char *str, const char *prefix); -// like str_has_prefix, but for paths. "ab/cd" is a path-prefix of "ab/cd/ef", but not "ab/cde". -// also handles the fact that \ and / are the same on windows +/// like str_has_prefix, but for paths. "ab/cd" is a path-prefix of "ab/cd/ef", but not "ab/cde". +/// also handles the fact that \ and / are the same on windows bool str_has_path_prefix(const char *path, const char *prefix); -// are these two strings equal? +/// are these two strings equal? bool streq(const char *a, const char *b); -// equivalent to the POSIX function strnlen +/// equivalent to the POSIX function strnlen size_t strn_len(const char *src, size_t n); -// equivalent to the POSIX function strndup +/// equivalent to the POSIX function strndup char *strn_dup(const char *src, size_t n); -// equivalent to the POSIX function strdup +/// equivalent to the POSIX function strdup char *str_dup(const char *src); -// a safer version of strncat. `dst_sz` includes a null-terminator. +/// a safer version of strncat. `dst_sz` includes a null-terminator. void strn_cat(char *dst, size_t dst_sz, const char *src, size_t src_len); -// a safer version of strcat. `dst_sz` includes a null-terminator. +/// a safer version of strcat. `dst_sz` includes a null-terminator. void str_cat(char *dst, size_t dst_sz, const char *src); -// a safer version of strncpy. `dst_sz` includes a null-terminator. +/// a safer version of strncpy. `dst_sz` includes a null-terminator. void strn_cpy(char *dst, size_t dst_sz, const char *src, size_t src_len); -// a safer version of strcpy. `dst_sz` includes a null-terminator. +/// a safer version of strcpy. `dst_sz` includes a null-terminator. void str_cpy(char *dst, size_t dst_sz, const char *src); -// equivalent to GNU function asprintf (like sprintf, but allocates the string with malloc). +/// equivalent to GNU function asprintf (like sprintf, but allocates the string with malloc). char *a_sprintf(const char *fmt, ...); -// print some bytes. useful for debugging. +/// print some bytes. useful for debugging. void print_bytes(const u8 *bytes, size_t n); -// like strstr, but case-insensitive -// currently this uses a "naive" string searching algorithm so -// it may be O(len(haystack) * len(needle)) for certain strings. +/// like strstr, but case-insensitive +/// currently this uses a "naive" string searching algorithm so +/// it may be O(len(haystack) * len(needle)) for certain strings. char *strstr_case_insensitive(const char *haystack, const char *needle); -// like strcmp, but case-insensitive +/// like strcmp, but case-insensitive int strcmp_case_insensitive(const char *a, const char *b); -// like streq, but case-insensitive +/// like streq, but case-insensitive bool streq_case_insensitive(const char *a, const char *b); -// function to be passed into qsort for case insensitive sorting +/// function to be passed into qsort for case insensitive sorting int str_qsort_case_insensitive_cmp(const void *av, const void *bv); -// the actual file name part of the path; get rid of the containing directory. -// NOTE: the returned string is part of path, so you don't need to free it or anything. +/// the actual file name part of the path; get rid of the containing directory. +/// NOTE: the returned string is part of path, so you don't need to free it or anything. const char *path_filename(const char *path); -// is this an absolute path? +/// is this an absolute path? bool path_is_absolute(const char *path); -// assuming `dir` is an absolute path, returns the absolute path of `relpath`, relative to `dir`. +/// assuming `dir` is an absolute path, returns the absolute path of `relpath`, relative to `dir`. void path_full(const char *dir, const char *relpath, char *abspath, size_t abspath_size); -// returns true if the paths are the same. -// handles the fact that paths are case insensitive on windows and that \ is the same as /. -// a symbolic link is considered different from the file it points to, as are two hard -// links to the same file. +/// returns true if the paths are the same. +/// handles the fact that paths are case insensitive on windows and that \ is the same as /. +/// a symbolic link is considered different from the file it points to, as are two hard +/// links to the same file. bool paths_eq(const char *path1, const char *path2); -// equivalent to POSIX function chdir. +/// equivalent to POSIX function chdir. void change_directory(const char *path); -// copy file from src to dest -// returns true on success +/// copy file from src to dest +/// returns true on success bool copy_file(const char *src, const char *dst); -// like qsort, but with a context object which gets passed to the comparison function +/// like qsort, but with a context object which gets passed to the comparison function void qsort_with_context(void *base, size_t nmemb, size_t size, int (*compar)(void *, const void *, const void *), void *arg); |