From 39be8826936e2b7529157702938a83c5254ffd37 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Thu, 27 Oct 2016 19:45:41 -0400 Subject: [PATCH] post-stream, got miblo incrementors/decrementors started. added settings for code presentation. adding config file for code wrapping --- 4coder_API.html | 78 +++--- 4coder_auto_indent.cpp | 2 +- 4coder_custom_api.h | 7 + 4coder_default_bindings.cpp | 94 +++++++- 4coder_default_include.cpp | 22 +- 4coder_types.h | 18 ++ 4cpp_lexer.h | 14 +- 4ed.cpp | 4 + 4ed_api_implementation.cpp | 27 +++ 4ed_app_models.h | 3 + 4ed_file.cpp | 8 +- 4ed_file_view.cpp | 25 +- 4ed_gui.cpp | 6 +- TODO.txt | 8 +- buffer/4coder_buffer_abstract.cpp | 10 +- package.bat | 44 ---- power/4coder_experiments.cpp | 9 + power/4coder_miblo_numbers.cpp | 381 ++++++++++++++++++++++++++++++ 18 files changed, 618 insertions(+), 142 deletions(-) create mode 100644 power/4coder_miblo_numbers.cpp diff --git a/4coder_API.html b/4coder_API.html index b0d1fd9c..d17f8d00 100644 --- a/4coder_API.html +++ b/4coder_API.html @@ -2,7 +2,7 @@

4coder API

Table of Contents

§1 Introduction

This is the documentation for the 4cpp lexer version 1.1. The documentation is the newest piece of this lexer project so it may still have problems. What is here should be correct and mostly complete.

If you have questions or discover errors please contact editor@4coder.net or to get help from community members you can post on the 4coder forums hosted on handmade.network at 4coder.handmade.network

This is the documentation for alpha 4.0.12 The documentation is still under construction so some of the links are linking to sections that have not been written yet. What is here should be correct and I suspect useful even without some of the other sections.

If you have questions or discover errors please contact editor@4coder.net or to get help from community members you can post on the 4coder forums hosted on handmade.network at 4coder.handmade.network

§2 4coder Systems

Coming Soon
-

§3 Types and Functions

§3.1 Function List

§3.2 Type List

§3.3 Function Descriptions

§3.3.1: exec_command

bool32 exec_command(
Application_Links *app,
Command_ID command_id
)
Parameters
command_id
The command_id parameter specifies which internal command to execute.
Return
This call returns non-zero if command_id named a valid internal command.
Description
A call to exec_command executes an internal command. +

§3 Types and Functions

§3.1 Function List

§3.2 Type List

§3.3 Function Descriptions

§3.3.1: exec_command

bool32 exec_command(
Application_Links *app,
Command_ID command_id
)
Parameters
command_id
The command_id parameter specifies which internal command to execute.
Return
This call returns non-zero if command_id named a valid internal command.
Description
A call to exec_command executes an internal command. If command_id is invalid a warning is posted to *messages*.

See Also

§3.3.2: exec_system_command

bool32 exec_system_command(
Application_Links *app,
View_Summary *view,
Buffer_Identifier buffer,
char *path,
int32_t path_len,
char *command,
int32_t command_len,
Command_Line_Interface_Flag flags
)
Parameters
view
If the view parameter is non-null it specifies a view to display the command's output buffer.
buffer
The buffer the command will output to is specified by the buffer parameter. See Buffer_Identifier for information on how this type specifies a buffer.
path
The path parameter specifies the path in which the command shall be executed. The string need not be null terminated.
path_len
The parameter path_len specifies the length of the path string.
command
The command parameter specifies the command that shall be executed. The string need not be null terminated.
command_len
The parameter command_len specifies the length of the command string.
flags
Flags for the behavior of the call are specified in the flags parameter.
Return
This call returns non-zero on success.
Description
A call to exec_system_command executes a command as if called from the command line, and sends the output to a buffer. The buffer identifier can either name a new buffer that does not exist, name a buffer that does @@ -79,31 +79,31 @@ accessed in the GUI. Whenever the GUI is opened it shows the hot directory.
In the future this will be deprecated and eliminated in favor of more flexible directories controlled on the custom side.


§3.3.56: get_file_list

File_List get_file_list(
Application_Links *app,
char *dir,
int32_t len
)
Parameters
dir
This parameter specifies the directory whose files will be enumerated in the returned list; it need not be null terminated.
len
This parameter the length of the dir string.
Return
This call returns a File_List struct containing pointers to the names of the files in the specified directory. The File_List returned should be passed to free_file_list -when it is no longer in use.

§3.3.57: free_file_list

void free_file_list(
Application_Links *app,
File_List list
)
Parameters
list
This parameter provides the file list to be freed.
Description
After this call the file list passed in should not be read or written to.


§3.3.58: memory_allocate

void* memory_allocate(
Application_Links *app,
int32_t size
)
Parameters
size
The size in bytes of the block that should be returned.
Description
This calls to a low level OS allocator which means it is best used +when it is no longer in use.

§3.3.57: free_file_list

void free_file_list(
Application_Links *app,
File_List list
)
Parameters
list
This parameter provides the file list to be freed.
Description
After this call the file list passed in should not be read or written to.


§3.3.58: set_gui_up_down_keys

void set_gui_up_down_keys(
Application_Links *app,
int16_t up_key,
int16_t down_key
)
No documentation generated for this function.

§3.3.59: memory_allocate

void* memory_allocate(
Application_Links *app,
int32_t size
)
Parameters
size
The size in bytes of the block that should be returned.
Description
This calls to a low level OS allocator which means it is best used for infrequent, large allocations. The size of the block must be remembered -if it will be freed or if it's mem protection status will be changed.

See Also

§3.3.59: memory_set_protection

bool32 memory_set_protection(
Application_Links *app,
void *ptr,
int32_t size,
Memory_Protect_Flags flags
)
Parameters
ptr
The base of the block on which to set memory protection flags.
size
The size that was originally used to allocate this block.
flags
The new memory protection flags.
Description
This call sets the memory protection flags of a block of memory that was previously -allocate by memory_allocate.

See Also

§3.3.60: memory_free

void memory_free(
Application_Links *app,
void *ptr,
int32_t size
)
Parameters
mem
The base of a block to free.
size
The size that was originally used to allocate this block.
Description
This call frees a block of memory that was previously allocated by -memory_allocate.

See Also

§3.3.61: file_exists

bool32 file_exists(
Application_Links *app,
char *filename,
int32_t len
)
Parameters
filename
This parameter specifies the full path to a file; it need not be null terminated.
len
This parameter specifies the length of the filename string.
Return
This call returns non-zero if and only if the file exists.

§3.3.62: directory_cd

bool32 directory_cd(
Application_Links *app,
char *dir,
int32_t *len,
int32_t capacity,
char *rel_path,
int32_t rel_len
)
Parameters
dir
This parameter provides a character buffer that stores a directory; it need not be null terminated.
len
This parameter specifies the length of the dir string.
capacity
This parameter specifies the maximum size of the dir string.
rel_path
This parameter specifies the path to change to, may include '.' or '..'; it need not be null terminated.
rel_len
This parameter specifies the length of the rel_path string.
Return
This call returns non-zero if the call succeeds.
Description
This call succeeds if the new directory exists and the it fits inside the +if it will be freed or if it's mem protection status will be changed.

See Also

§3.3.60: memory_set_protection

bool32 memory_set_protection(
Application_Links *app,
void *ptr,
int32_t size,
Memory_Protect_Flags flags
)
Parameters
ptr
The base of the block on which to set memory protection flags.
size
The size that was originally used to allocate this block.
flags
The new memory protection flags.
Description
This call sets the memory protection flags of a block of memory that was previously +allocate by memory_allocate.

See Also

§3.3.61: memory_free

void memory_free(
Application_Links *app,
void *ptr,
int32_t size
)
Parameters
mem
The base of a block to free.
size
The size that was originally used to allocate this block.
Description
This call frees a block of memory that was previously allocated by +memory_allocate.

See Also

§3.3.62: file_exists

bool32 file_exists(
Application_Links *app,
char *filename,
int32_t len
)
Parameters
filename
This parameter specifies the full path to a file; it need not be null terminated.
len
This parameter specifies the length of the filename string.
Return
This call returns non-zero if and only if the file exists.

§3.3.63: directory_cd

bool32 directory_cd(
Application_Links *app,
char *dir,
int32_t *len,
int32_t capacity,
char *rel_path,
int32_t rel_len
)
Parameters
dir
This parameter provides a character buffer that stores a directory; it need not be null terminated.
len
This parameter specifies the length of the dir string.
capacity
This parameter specifies the maximum size of the dir string.
rel_path
This parameter specifies the path to change to, may include '.' or '..'; it need not be null terminated.
rel_len
This parameter specifies the length of the rel_path string.
Return
This call returns non-zero if the call succeeds.
Description
This call succeeds if the new directory exists and the it fits inside the dir buffer. If the call succeeds the dir buffer is filled with the new directory and len is overwritten with the length of the new string in the buffer.

For instance if dir contains "C:/Users/MySelf" and rel is "Documents" the buffer will contain "C:/Users/MySelf/Documents" and len will contain the length of that string. This call can also be used with rel set to ".." to traverse to parent -folders.


§3.3.63: get_4ed_path

bool32 get_4ed_path(
Application_Links *app,
char *out,
int32_t capacity
)
Parameters
out
This parameter provides a character buffer that receives the path to the 4ed executable file.
capacity
This parameter specifies the maximum capacity of the out buffer.
Return
This call returns non-zero on success.

§3.3.64: show_mouse_cursor

void show_mouse_cursor(
Application_Links *app,
Mouse_Cursor_Show_Type show
)
Parameters
show
This parameter specifies the new state of the mouse cursor.
See Also

§3.3.65: toggle_fullscreen

void toggle_fullscreen(
Application_Links *app
)
Description
This call tells 4coder to switch into or out of full screen mode. +folders.


§3.3.64: get_4ed_path

bool32 get_4ed_path(
Application_Links *app,
char *out,
int32_t capacity
)
Parameters
out
This parameter provides a character buffer that receives the path to the 4ed executable file.
capacity
This parameter specifies the maximum capacity of the out buffer.
Return
This call returns non-zero on success.

§3.3.65: show_mouse_cursor

void show_mouse_cursor(
Application_Links *app,
Mouse_Cursor_Show_Type show
)
Parameters
show
This parameter specifies the new state of the mouse cursor.
See Also

§3.3.66: toggle_fullscreen

void toggle_fullscreen(
Application_Links *app
)
Description
This call tells 4coder to switch into or out of full screen mode. The changes of full screen mode do not take effect until the end of the current frame. On Windows this call will not work unless 4coder was started in "stream mode". -Stream mode can be enabled with -S or -F flags on the command line to 4ed.


§3.3.66: is_fullscreen

bool32 is_fullscreen(
Application_Links *app
)
Description
This call returns true if the 4coder is in full screen mode. This call +Stream mode can be enabled with -S or -F flags on the command line to 4ed.


§3.3.67: is_fullscreen

bool32 is_fullscreen(
Application_Links *app
)
Description
This call returns true if the 4coder is in full screen mode. This call takes toggles that have already occured this frame into account. So it may return true even though the frame has not ended and actually put 4coder into full screen. If it returns true though, 4coder will definitely be full screen by the beginning of the next -frame if the state is not changed.


§3.3.67: send_exit_signal

void send_exit_signal(
Application_Links *app
)
Description
This call sends a signal to 4coder to attempt to exit. If there are unsaved +frame if the state is not changed.


§3.3.68: send_exit_signal

void send_exit_signal(
Application_Links *app
)
Description
This call sends a signal to 4coder to attempt to exit. If there are unsaved files this triggers a dialogue ensuring you're okay with closing.


§3.4 Type Descriptions

§3.4.1: bool32

typedef int32_t bool32;
Description
bool32 is an alias name to signal that an integer parameter or field is for true/false vales.


§3.4.2: int_color

typedef uint32_t int_color;
Description
int_color is an alias name to signal that an integer parameter or field is for a color value, colors are specified as 24 bit integers in 3 channels: 0xRRGGBB.


§3.4.3: Key_Code

typedef unsigned char Key_Code;
Description
Key_Code is the alias for key codes including raw codes and codes translated to textual input that takes modifiers into account.


§3.4.4: Buffer_ID

typedef int32_t Buffer_ID;
Description
Buffer_ID is used to name a 4coder buffer. Each buffer has a unique id but when a buffer is closed it's id may be recycled by future, different buffers.


§3.4.5: View_ID

typedef int32_t View_ID;
Description
View_ID is used to name a 4coder view. Each view has a unique id in the interval [1,16].


§3.4.6: Key_Modifier

enum Key_Modifier;
Description
A Key_Modifier acts as an index for specifying modifiers in arrays.

Values
MDFR_SHIFT_INDEX
MDFR_CONTROL_INDEX
MDFR_ALT_INDEX
MDFR_CAPS_INDEX
MDFR_HOLD_INDEX
MDFR_INDEX_COUNT
MDFR_INDEX_COUNT is used to specify the number of modifiers supported.


§3.4.7: Key_Modifier_Flag

enum Key_Modifier_Flag;
Description
A Key_Modifier_Flag field is used to specify a specific state of modifiers. -Flags can be combined with bit or to specify a state with multiple modifiers.

Values
MDFR_NONE = 0x0
MDFR_NONE specifies that no modifiers are pressed.

MDFR_CTRL = 0x1
MDFR_ALT = 0x2
MDFR_SHIFT = 0x4

§3.4.8: Command_ID

enum Command_ID;
Description
A Command_ID is used as a name for commands implemented internally in 4coder.

Values
cmdid_null
cmdid_null is set aside to always be zero and is not associated with any command.

cmdid_undo
cmdid_undo performs a standard undo behavior.

cmdid_redo
cmdid_redo reperforms an edit that was undone.

cmdid_history_backward
cmdid_history_backward performs a step backwards through the file history, which includes previously lost redo branches.

cmdid_history_forward
cmdid_history_forward unperforms the previous cmdid_history_backward step if possible.

cmdid_interactive_new
cmdid_interactive_new begins an interactive dialogue to create a new buffer.

cmdid_interactive_open
cmdid_interactive_open begins an interactive dialogue to open a file into a buffer.

cmdid_save_as
cmdid_save_as does not currently work and is likely to be removed rather that fixed.

cmdid_interactive_switch_buffer
cmdid_interactive_switch_buffer begins an interactive dialogue to choose an open buffer to swap into the active view.

cmdid_interactive_kill_buffer
cmdid_interactive_kill_buffer begins an interactive dialogue to choose an open buffer to kill.

cmdid_reopen
cmdid_reopen reloads the active buffer's associated file and discards the old buffer contents for the reloaded file.

cmdid_save
cmdid_save saves the buffer's contents into the associated file.

cmdid_kill_buffer
cmdid_kill_buffer tries to kill the active buffer.

cmdid_open_color_tweaker
cmdid_open_color_tweaker opens the theme editing GUI.

cmdid_open_config
cmdid_open_config opens the configuration menu.

cmdid_open_menu
cmdid_open_menu opens the top level menu.

cmdid_open_debug
cmdid_open_debug opens the debug information viewer mode.

cmdid_count

§3.4.9: Memory_Protect_Flags

enum Memory_Protect_Flags;
Description
TODO

Values
MemProtect_Read = 0x1
TODO

MemProtect_Write = 0x2
TODO

MemProtect_Execute = 0x4
TODO


§3.4.10: User_Input_Type_ID

enum User_Input_Type_ID;
Description
User_Input_Type_ID specifies a type of user input event.

Values
UserInputNone
UserInputNone indicates that no event has occurred.

UserInputKey
UserInputKey indicates an event which can be described by a Key_Event_Data struct.

UserInputMouse
UserInputMouse indicates an event which can be described by a Mouse_State struct.


§3.4.11: Event_Message_Type_ID

enum Event_Message_Type_ID;
Description
Event_Message_Type_ID is a part of an unfinished feature.

Values
EventMessage_NoMessage
TODO.

EventMessage_OpenView
TODO.

EventMessage_Frame
TODO.

EventMessage_CloseView
TODO.


§3.4.12: Buffer_Setting_ID

enum Buffer_Setting_ID;
Description
A Buffer_Setting_ID names a setting in a buffer.

Values
BufferSetting_Null
BufferSetting_Null is not a valid setting, it is reserved to detect errors.

BufferSetting_Lex
The BufferSetting_Lex setting is used to determine whether to store C++ tokens +Flags can be combined with bit or to specify a state with multiple modifiers.

Values
MDFR_NONE = 0x0
MDFR_NONE specifies that no modifiers are pressed.

MDFR_CTRL = 0x1
MDFR_ALT = 0x2
MDFR_SHIFT = 0x4

§3.4.8: Command_ID

enum Command_ID;
Description
A Command_ID is used as a name for commands implemented internally in 4coder.

Values
cmdid_null
cmdid_null is set aside to always be zero and is not associated with any command.

cmdid_undo
cmdid_undo performs a standard undo behavior.

cmdid_redo
cmdid_redo reperforms an edit that was undone.

cmdid_history_backward
cmdid_history_backward performs a step backwards through the file history, which includes previously lost redo branches.

cmdid_history_forward
cmdid_history_forward unperforms the previous cmdid_history_backward step if possible.

cmdid_interactive_new
cmdid_interactive_new begins an interactive dialogue to create a new buffer.

cmdid_interactive_open
cmdid_interactive_open begins an interactive dialogue to open a file into a buffer.

cmdid_save_as
cmdid_save_as does not currently work and is likely to be removed rather that fixed.

cmdid_interactive_switch_buffer
cmdid_interactive_switch_buffer begins an interactive dialogue to choose an open buffer to swap into the active view.

cmdid_interactive_kill_buffer
cmdid_interactive_kill_buffer begins an interactive dialogue to choose an open buffer to kill.

cmdid_reopen
cmdid_reopen reloads the active buffer's associated file and discards the old buffer contents for the reloaded file.

cmdid_save
cmdid_save saves the buffer's contents into the associated file.

cmdid_kill_buffer
cmdid_kill_buffer tries to kill the active buffer.

cmdid_open_color_tweaker
cmdid_open_color_tweaker opens the theme editing GUI.

cmdid_open_config
cmdid_open_config opens the configuration menu.

cmdid_open_menu
cmdid_open_menu opens the top level menu.

cmdid_open_debug
cmdid_open_debug opens the debug information viewer mode.

cmdid_count

§3.4.9: Memory_Protect_Flags

enum Memory_Protect_Flags;
Description
TODO

Values
MemProtect_Read = 0x1
TODO

MemProtect_Write = 0x2
TODO

MemProtect_Execute = 0x4
TODO


§3.4.10: User_Input_Type_ID

enum User_Input_Type_ID;
Description
User_Input_Type_ID specifies a type of user input event.

Values
UserInputNone
UserInputNone indicates that no event has occurred.

UserInputKey
UserInputKey indicates an event which can be described by a Key_Event_Data struct.

UserInputMouse
UserInputMouse indicates an event which can be described by a Mouse_State struct.


§3.4.11: Event_Message_Type_ID

enum Event_Message_Type_ID;
Description
Event_Message_Type_ID is a part of an unfinished feature.

Values
EventMessage_NoMessage
TODO.

EventMessage_OpenView
TODO.

EventMessage_Frame
TODO.

EventMessage_CloseView
TODO.


§3.4.12: Wrap_Indicator_Mode

enum Wrap_Indicator_Mode;
Description
A Wrap_Indicator_Mode is used in the buffer setting BufferSetting_WrapIndicator to specify how to indicate that line has been wrapped.

Values
WrapIndicator_Hide
WrapIndicator_Hide tells the buffer rendering system not to put any indicator on wrapped lines.

WrapIndicator_Show_After_Line
WrapIndicator_Show_After_Line tells the buffer rendering system to put a backslash indicator on wrapped lines right after the last character of the line.

WrapIndicator_Show_At_Wrap_Edge
WrapIndicator_Show_At_Wrap_Edge tells the buffer rendering system to put a backslash indicator on wrapped lines aligned with the wrap position for that line.


§3.4.13: Buffer_Setting_ID

enum Buffer_Setting_ID;
Description
A Buffer_Setting_ID names a setting in a buffer.

Values
BufferSetting_Null
BufferSetting_Null is not a valid setting, it is reserved to detect errors.

BufferSetting_Lex
The BufferSetting_Lex setting is used to determine whether to store C++ tokens from with the buffer.

BufferSetting_WrapLine
The BufferSetting_WrapLine setting is used to determine whether a buffer prefers to be viewed with wrapped lines, individual views can be set to override this value after being tied to the buffer.

BufferSetting_WrapPosition
The BufferSetting_WrapPosition setting determines after how many pixels @@ -111,7 +111,7 @@ Flags can be combined with bit or to specify a state with multiple modifiers.

BufferSetting_MapID
The BufferSetting_MapID setting specifies the id of the command map that should be + best behavior try to only set this setting once per frame, if possible.

BufferSetting_MinimumBaseWrapPosition
The BufferSetting_MinimumBaseWrapPosition setting is used to increase the with in pixels allotted to a line for wrapping, by setting a minimum position away from the base of the line. The base of a line is always 0, or the left hand side of the view, in text files. In code files the base of a line is the amount the line is shifted to the right due to brace nesting. This setting allows for deeply nested code to remain readable by ensuring lines deep in the nesting get some minimum base width which may be more wrapping space than the non base adjusted wrap position would have allowed. In any case where the (default wrapping position) is greater than (the base + minimum base position), the larger

BufferSetting_WrapIndicator
The BufferSetting_WrapIndicator setting is used to specify how wrapped lines should be marked so the user can see that they have been wrapped. The value should be one of the values in the Wrap_Indicator_Mode enum.

BufferSetting_MapID
The BufferSetting_MapID setting specifies the id of the command map that should be active when a buffer is active.

BufferSetting_Eol
The BufferSetting_Eol setting specifies how line ends should be saved to the backing file. A 1 indicates dos endings "\r\n" and a 0 indicates nix endings "\n".

BufferSetting_Unimportant
The BufferSetting_Unimportant setting marks a buffer so that it's dirty state will be completely ignored. This means the "dirty" star is hidden and the buffer can be closed without presenting an @@ -119,13 +119,13 @@ Flags can be combined with bit or to specify a state with multiple modifiers.

BufferSetting_VirtualWhitespace
The BufferSetting_VirtualWhitespace settings enables virtual whitespace on a buffer. Text buffers with virtual whitespace will set the indentation of every line to zero. - Buffers with lexing enabled will use virtual white space to present the code with appealing indentation.


§3.4.13: View_Setting_ID

enum View_Setting_ID;
Description
A View_Setting_ID names an adjustable setting in a view.

Values
ViewSetting_Null
ViewSetting_Null is not a valid setting, it is reserved to detect errors.

ViewSetting_ShowWhitespace
The ViewSetting_ShowWhitespace setting determines whether the view highlights + Buffers with lexing enabled will use virtual white space to present the code with appealing indentation.


§3.4.14: View_Setting_ID

enum View_Setting_ID;
Description
A View_Setting_ID names an adjustable setting in a view.

Values
ViewSetting_Null
ViewSetting_Null is not a valid setting, it is reserved to detect errors.

ViewSetting_ShowWhitespace
The ViewSetting_ShowWhitespace setting determines whether the view highlights whitespace in a file. Whenever the view switches to a new buffer this setting is turned off.

ViewSetting_ShowScrollbar
The ViewSetting_ShowScrollbar setting determines whether a scroll bar is - attached to a view in it's scrollable section.


§3.4.14: Buffer_Create_Flag

enum Buffer_Create_Flag;
Description
A Buffer_Create_Flag field specifies how a buffer should be created.

Values
BufferCreate_Background = 0x1
BufferCreate_Background is not currently implemented.

BufferCreate_AlwaysNew = 0x2
When BufferCreate_AlwaysNew is set it indicates the buffer should be + attached to a view in it's scrollable section.


§3.4.15: Buffer_Create_Flag

enum Buffer_Create_Flag;
Description
A Buffer_Create_Flag field specifies how a buffer should be created.

Values
BufferCreate_Background = 0x1
BufferCreate_Background is not currently implemented.

BufferCreate_AlwaysNew = 0x2
When BufferCreate_AlwaysNew is set it indicates the buffer should be cleared to empty even if it's associated file already has content.

BufferCreate_NeverNew = 0x4
When BufferCreate_NeverNew is set it indicates that the buffer should only be created if it is an existing file or if a buffer with the given name - is already open.


§3.4.15: Buffer_Creation_Data

struct Buffer_Creation_Data { /* non-public internals */ } ;
Description
TODO


§3.4.16: Buffer_Kill_Flag

enum Buffer_Kill_Flag;
Description
A Buffer_Kill_Flag field specifies how a buffer should be killed.

Values
BufferKill_Background = 0x1
BufferKill_Background is not currently implemented.

BufferKill_AlwaysKill = 0x2
When BufferKill_AlwaysKill is set it indicates the buffer should be killed - without asking, even when the buffer is dirty.


§3.4.17: Access_Flag

enum Access_Flag;
Description
An Access_Flag field specifies what sort of permission you grant to an + is already open.


§3.4.16: Buffer_Creation_Data

struct Buffer_Creation_Data { /* non-public internals */ } ;
Description
TODO


§3.4.17: Buffer_Kill_Flag

enum Buffer_Kill_Flag;
Description
A Buffer_Kill_Flag field specifies how a buffer should be killed.

Values
BufferKill_Background = 0x1
BufferKill_Background is not currently implemented.

BufferKill_AlwaysKill = 0x2
When BufferKill_AlwaysKill is set it indicates the buffer should be killed + without asking, even when the buffer is dirty.


§3.4.18: Access_Flag

enum Access_Flag;
Description
An Access_Flag field specifies what sort of permission you grant to an access call. An access call is usually one the returns a summary struct. If a 4coder object has a particular protection flag set and the corresponding bit is not set in the access field, that 4coder object is hidden. On the other hand if @@ -135,72 +135,72 @@ that protection flag, the object is still returned from the access call.

the output from an app->exec_system_command call such as *build*. This is to prevent the user from accidentally editing output that they might prefer to keep in tact.

AccessHidden = 0x2
AccessHidden is set on any view that is not currently showing it's file, for instance because it is navigating the file system to open a file.

AccessAll = 0xFF
AccessAll is a catchall access for cases where an access call should always - return an object no matter what it's protection flags are.


§3.4.18: Dirty_State

enum Dirty_State;
Description
A Dirty_State value describes whether changes have been made to a buffer + return an object no matter what it's protection flags are.


§3.4.19: Dirty_State

enum Dirty_State;
Description
A Dirty_State value describes whether changes have been made to a buffer or to an underlying file since the last sync time between the two. Saving a buffer to it's file or loading the buffer from the file both act as sync points.

Values
DirtyState_UpToDate = 0
DirtyState_UpToDate indicates that there are no unsaved changes and the underlying system file still agrees with the buffer's state.

DirtyState_UnsavedChanges = 1
DirtyState_UnsavedChanges indicates that there have been changes in the buffer since the last sync point.

DirtyState_UnloadedChanges = 2
DirtyState_UnsavedChanges indicates that the underlying file has been - edited since the last sync point with the buffer.


§3.4.19: Seek_Boundary_Flag

enum Seek_Boundary_Flag;
Description
A Seek_Boundary_Flag field specifies a set of "boundary" types used in seeks for the -beginning or end of different types of words.

Values
BoundaryWhitespace = 0x1
BoundaryToken = 0x2
BoundaryAlphanumeric = 0x4
BoundaryCamelCase = 0x8

§3.4.20: Command_Line_Interface_Flag

enum Command_Line_Interface_Flag;
Description
A Command_Line_Interface_Flag field specifies the behavior of a call to a command line interface.

Values
CLI_OverlapWithConflict = 0x1
If CLI_OverlapWithConflict is set if output buffer of the new command is already + edited since the last sync point with the buffer.


§3.4.20: Seek_Boundary_Flag

enum Seek_Boundary_Flag;
Description
A Seek_Boundary_Flag field specifies a set of "boundary" types used in seeks for the +beginning or end of different types of words.

Values
BoundaryWhitespace = 0x1
BoundaryToken = 0x2
BoundaryAlphanumeric = 0x4
BoundaryCamelCase = 0x8

§3.4.21: Command_Line_Interface_Flag

enum Command_Line_Interface_Flag;
Description
A Command_Line_Interface_Flag field specifies the behavior of a call to a command line interface.

Values
CLI_OverlapWithConflict = 0x1
If CLI_OverlapWithConflict is set if output buffer of the new command is already in use by another command which is still executing, the older command relinquishes control of the buffer and both operate simultaneously with only the newer command outputting to the buffer.

CLI_AlwaysBindToView = 0x2
If CLI_AlwaysBindToView is set the output buffer will always be set in the active view even if it is already set in another open view.

CLI_CursorAtEnd = 0x4
If CLI_CursorAtEnd is set the cursor will be kept at the end of the output buffer, - otherwise the cursor is kept at the beginning.


§3.4.21: Auto_Indent_Flag

enum Auto_Indent_Flag;
Description
An Auto_Indent_Flag field specifies the behavior of an auto indentation operation.

Values
AutoIndent_ClearLine = 0x1
If AutoIndent_ClearLine is set, then any line that is only whitespace will + otherwise the cursor is kept at the beginning.


§3.4.22: Auto_Indent_Flag

enum Auto_Indent_Flag;
Description
An Auto_Indent_Flag field specifies the behavior of an auto indentation operation.

Values
AutoIndent_ClearLine = 0x1
If AutoIndent_ClearLine is set, then any line that is only whitespace will be cleared to contain nothing at all. otherwise the line is filled with whitespace to match the nearby indentation.

AutoIndent_UseTab = 0x2
If AutoIndent_UseTab is set, then when putting in leading whitespace to align code, as many tabs will be used as possible until the fine grained control of spaces is needed to finish the alignment.

AutoIndent_ExactAlignBlock = 0x4
If AutoIndent_ExactAlignBlock is set, then block comments are indented by putting the first non-whitespace character of the line in line with the beginning of the comment.

AutoIndent_FullTokens = 0x8
If AutoIndent_FullTokens is set, then the set of lines that are indented is - automatically expanded so that any token spanning multiple lines gets entirely indented.


§3.4.22: Set_Buffer_Flag

enum Set_Buffer_Flag;
Description
A Set_Buffer_Flag field specifies the behavior of an operation that sets the buffer of a view.

Values
SetBuffer_KeepOriginalGUI = 0x1
If SetBuffer_KeepOriginalGUI then when the file is set, the view will not switch to it + automatically expanded so that any token spanning multiple lines gets entirely indented.


§3.4.23: Set_Buffer_Flag

enum Set_Buffer_Flag;
Description
A Set_Buffer_Flag field specifies the behavior of an operation that sets the buffer of a view.

Values
SetBuffer_KeepOriginalGUI = 0x1
If SetBuffer_KeepOriginalGUI then when the file is set, the view will not switch to it if some other GUI was currently up, otherwise any GUI that is up is closed and the view - switches to the file.


§3.4.23: Input_Type_Flag

enum Input_Type_Flag;
Description
A Input_Type_Flag field specifies a set of input event types.

Values
EventOnAnyKey = 0x1
If EventOnAnyKey is set, all keyboard events are included in the set.

EventOnEsc = 0x2
If EventOnEsc is set, any press of the escape key is included in the set.

EventOnLeftButton = 0x4
If EventOnLeftButton is set, left clicks are included in the set.

EventOnRightButton = 0x8
If EventOnRightButton is set, right clicks are included in the set.

EventOnWheel = 0x10
If EventOnWheel is set, any wheel movement is included in the set.

EventOnMouseMove = 0x20
This is not totally implemented yet.

EventOnButton = (EventOnLeftButton | EventOnRightButton | EventOnWheel)
If EventOnButton is set, all mouse button events are included in the set.

EventOnMouse = (EventOnButton | EventOnMouseMove)
This is not totally implemented yet.

EventAll = 0xFF
EventAll is a catch all name for including all possible events in the set.


§3.4.24: Mouse_Cursor_Show_Type

enum Mouse_Cursor_Show_Type;
Description
A Mouse_Cursor_Show_Type value specifes a mode for 4coder to handle the mouse cursor.

Values
MouseCursorShow_Never
The MouseCursorShow_Never mode never shows the cursor.

MouseCursorShow_Always
The MouseCursorShow_Never mode always shows the cursor.


§3.4.25: View_Split_Position

enum View_Split_Position;
Description
A View_Split_Position specifies where a new view should be placed as a result of -a view split operation.

Values
ViewSplit_Top
This value indicates that the new view should be above the existing view.

ViewSplit_Bottom
This value indicates that the new view should be below the existing view.

ViewSplit_Left
This value indicates that the new view should be left of the existing view.

ViewSplit_Right
This value indicates that the new view should be right of the existing view.


§3.4.26: Generic_Command

union Generic_Command {
Command_ID cmdid;
Custom_Command_Function * command;
};
Description
Generic_Command acts as a name for a command, and can name an + switches to the file.


§3.4.24: Input_Type_Flag

enum Input_Type_Flag;
Description
A Input_Type_Flag field specifies a set of input event types.

Values
EventOnAnyKey = 0x1
If EventOnAnyKey is set, all keyboard events are included in the set.

EventOnEsc = 0x2
If EventOnEsc is set, any press of the escape key is included in the set.

EventOnLeftButton = 0x4
If EventOnLeftButton is set, left clicks are included in the set.

EventOnRightButton = 0x8
If EventOnRightButton is set, right clicks are included in the set.

EventOnWheel = 0x10
If EventOnWheel is set, any wheel movement is included in the set.

EventOnMouseMove = 0x20
This is not totally implemented yet.

EventOnButton = (EventOnLeftButton | EventOnRightButton | EventOnWheel)
If EventOnButton is set, all mouse button events are included in the set.

EventOnMouse = (EventOnButton | EventOnMouseMove)
This is not totally implemented yet.

EventAll = 0xFF
EventAll is a catch all name for including all possible events in the set.


§3.4.25: Mouse_Cursor_Show_Type

enum Mouse_Cursor_Show_Type;
Description
A Mouse_Cursor_Show_Type value specifes a mode for 4coder to handle the mouse cursor.

Values
MouseCursorShow_Never
The MouseCursorShow_Never mode never shows the cursor.

MouseCursorShow_Always
The MouseCursorShow_Never mode always shows the cursor.


§3.4.26: View_Split_Position

enum View_Split_Position;
Description
A View_Split_Position specifies where a new view should be placed as a result of +a view split operation.

Values
ViewSplit_Top
This value indicates that the new view should be above the existing view.

ViewSplit_Bottom
This value indicates that the new view should be below the existing view.

ViewSplit_Left
This value indicates that the new view should be left of the existing view.

ViewSplit_Right
This value indicates that the new view should be right of the existing view.


§3.4.27: Generic_Command

union Generic_Command {
Command_ID cmdid;
Custom_Command_Function * command;
};
Description
Generic_Command acts as a name for a command, and can name an internal command or a custom command.

Fields
cmdid
If this Generic_Command represents an internal command the cmdid field will have a value less than cmdid_count, and this field is the command id for the command.

command
If this Generic_Command does not represent an internal command the command - field is the pointer to the custom command..


§3.4.27: Key_Event_Data

struct Key_Event_Data {
Key_Code keycode;
Key_Code character;
Key_Code character_no_caps_lock;
char modifiers[MDFR_INDEX_COUNT];
};
Description
Key_Event_Data describes a key event, including the + field is the pointer to the custom command..


§3.4.28: Key_Event_Data

struct Key_Event_Data {
Key_Code keycode;
Key_Code character;
Key_Code character_no_caps_lock;
char modifiers[MDFR_INDEX_COUNT];
};
Description
Key_Event_Data describes a key event, including the translation to a character, the translation to a character ignoring the state of caps lock, and an array of all the modifiers that were pressed at the time of the event.

Fields
keycode
This field is the raw keycode which is always non-zero in valid key events.

character
This field is the keycode after translation to a character, this is 0 if there is no translation.

character_no_caps_lock
This field is like the field character, except that the state of caps lock is ignored in the translation.

modifiers
This field is an array indicating the state of modifiers at the time of the key press. The array is indexed using the values of Key_Modifier. A 1 indicates that the corresponding - modifier was held, and a 0 indicates that it was not held.


§3.4.28: Mouse_State

struct Mouse_State {
char l;
char r;
char press_l;
char press_r;
char release_l;
char release_r;
char wheel;
char out_of_window;
int32_t x;
int32_t y;
};
Description
Mouse_State describes an entire mouse state complete with the + modifier was held, and a 0 indicates that it was not held.


§3.4.29: Mouse_State

struct Mouse_State {
char l;
char r;
char press_l;
char press_r;
char release_l;
char release_r;
char wheel;
char out_of_window;
int32_t x;
int32_t y;
};
Description
Mouse_State describes an entire mouse state complete with the position, left and right button states, the wheel state, and whether -or not the mouse if in the window.

Fields
l
This field indicates that the left button is held.

r
This field indicates that the right button is held.

press_l
This field indicates that the left button was pressed this frame.

press_r
This field indicates that the right button was pressed this frame.

release_l
This field indicates that the left button was released this frame.

release_r
This field indicates that the right button was released this frame.

wheel
This field is 0 when the wheel has not moved, it is 1 for a downward motion and -1 for an upward motion.

out_of_window
This field indicates that the mouse is outside of the window.

x
This field contains the x position of the mouse relative to the window where the left side is 0.

y
This field contains the y position of the mouse relative to the window where the top side is 0.


§3.4.29: Range

union Range {
struct {
int32_t min;
int32_t max;
};
struct {
int32_t start;
int32_t end;
};
};
Description
Range describes an integer range typically used for ranges within a buffer. +or not the mouse if in the window.

Fields
l
This field indicates that the left button is held.

r
This field indicates that the right button is held.

press_l
This field indicates that the left button was pressed this frame.

press_r
This field indicates that the right button was pressed this frame.

release_l
This field indicates that the left button was released this frame.

release_r
This field indicates that the right button was released this frame.

wheel
This field is 0 when the wheel has not moved, it is 1 for a downward motion and -1 for an upward motion.

out_of_window
This field indicates that the mouse is outside of the window.

x
This field contains the x position of the mouse relative to the window where the left side is 0.

y
This field contains the y position of the mouse relative to the window where the top side is 0.


§3.4.30: Range

union Range {
struct {
int32_t min;
int32_t max;
};
struct {
int32_t start;
int32_t end;
};
};
Description
Range describes an integer range typically used for ranges within a buffer. Ranges tend are usually not passed as a Range struct into the API, but this struct is used to return ranges.

-Throughout the API ranges are thought of in the form [min,max

Fields
min
This is the smaller value in the range, it is also the 'start'.

max
This is the larger value in the range, it is also the 'end'.

start
This is the start of the range, it is also the 'min'.

end
This is the end of the range, it is also the 'max'.


§3.4.30: File_Info

struct File_Info {
char * filename;
int32_t filename_len;
int32_t folder;
};
Description
File_Info describes the name and type of a file.

Fields
filename
This field is a null terminated string specifying the name of the file.

filename_len
This field specifies the length of the filename string not counting the null terminator.

folder
This field indicates that the description is for a folder not a file.

See Also
File_List

§3.4.31: File_List

struct File_List {
void * block;
File_Info * infos;
int32_t count;
int32_t block_size;
};
Description
File_List is a list of File_Info structs.

Fields
block
This field is for inernal use.

infos
This field is an array of File_Info structs.

count
This field specifies the number of struts in the info array.

block_size
This field is for internal use.


§3.4.32: Buffer_Identifier

struct Buffer_Identifier {
char * name;
int32_t name_len;
int32_t id;
};
Description
Buffer_Identifier acts as a loosely typed description of a buffer that +Throughout the API ranges are thought of in the form [min,max

Fields
min
This is the smaller value in the range, it is also the 'start'.

max
This is the larger value in the range, it is also the 'end'.

start
This is the start of the range, it is also the 'min'.

end
This is the end of the range, it is also the 'max'.


§3.4.31: File_Info

struct File_Info {
char * filename;
int32_t filename_len;
int32_t folder;
};
Description
File_Info describes the name and type of a file.

Fields
filename
This field is a null terminated string specifying the name of the file.

filename_len
This field specifies the length of the filename string not counting the null terminator.

folder
This field indicates that the description is for a folder not a file.

See Also
File_List

§3.4.32: File_List

struct File_List {
void * block;
File_Info * infos;
int32_t count;
int32_t block_size;
};
Description
File_List is a list of File_Info structs.

Fields
block
This field is for inernal use.

infos
This field is an array of File_Info structs.

count
This field specifies the number of struts in the info array.

block_size
This field is for internal use.


§3.4.33: Buffer_Identifier

struct Buffer_Identifier {
char * name;
int32_t name_len;
int32_t id;
};
Description
Buffer_Identifier acts as a loosely typed description of a buffer that can either be a name or an id. If the

Fields
name
This field is the name of the buffer; it need not be null terminated. - If id is specified this pointer should be NULL.

name_len
This field specifies the length of the name string.

id
This field is the id of the buffer. If name is specified this should be 0.


§3.4.33: GUI_Scroll_Vars

struct GUI_Scroll_Vars {
float scroll_y;
int32_t target_y;
int32_t prev_target_y;
float scroll_x;
int32_t target_x;
int32_t prev_target_x;
};
Description
This struct is a part of an incomplete feature.

Fields
scroll_y
TODO

target_y
TODO

prev_target_y
TODO

scroll_x
TODO

target_x
TODO

prev_target_x
TODO


§3.4.34: Buffer_Seek_Type

enum Buffer_Seek_Type;
Description
The Buffer_Seek_Type is is used in a Buffer_Seek to identify which + If id is specified this pointer should be NULL.

name_len
This field specifies the length of the name string.

id
This field is the id of the buffer. If name is specified this should be 0.


§3.4.34: GUI_Scroll_Vars

struct GUI_Scroll_Vars {
float scroll_y;
int32_t target_y;
int32_t prev_target_y;
float scroll_x;
int32_t target_x;
int32_t prev_target_x;
};
Description
This struct is a part of an incomplete feature.

Fields
scroll_y
TODO

target_y
TODO

prev_target_y
TODO

scroll_x
TODO

target_x
TODO

prev_target_x
TODO


§3.4.35: Buffer_Seek_Type

enum Buffer_Seek_Type;
Description
The Buffer_Seek_Type is is used in a Buffer_Seek to identify which coordinates are suppose to be used for the seek.

Values
buffer_seek_pos
This value indicates absolute byte index positioning where positions are measured as the number of bytes from the start of the file.

buffer_seek_character_pos
This value indicates apparent character index positioning where positions are measured as the number of apparent characters from the starts of the file.

buffer_seek_wrapped_xy
This value indicates xy positioning with wrapped lines where the x and y values are in pixels.

buffer_seek_unwrapped_xy
This value indicates xy positioning with unwrapped lines where the x and y values are in pixels.

buffer_seek_line_char
This value indicates line-character positioning. - These coordinates are 1 based to match standard line numbering.

See Also
Buffer_Seek
4coder_Buffer_Positioning_System

§3.4.35: Buffer_Seek

struct Buffer_Seek {
Buffer_Seek_Type type;
union {
struct {
int32_t pos;
};
struct {
bool32 round_down;
float x;
float y;
};
struct {
int32_t line;
int32_t character;
};
};
};
Description
Buffer_Seek describes the destination of a seek operation. There are helpers + These coordinates are 1 based to match standard line numbering.

See Also
Buffer_Seek
4coder_Buffer_Positioning_System

§3.4.36: Buffer_Seek

struct Buffer_Seek {
Buffer_Seek_Type type;
union {
struct {
int32_t pos;
};
struct {
bool32 round_down;
float x;
float y;
};
struct {
int32_t line;
int32_t character;
};
};
};
Description
Buffer_Seek describes the destination of a seek operation. There are helpers for concisely creating Buffer_Seek structs. They can be found in 4coder_buffer_types.h.

Fields
type
The type field determines the coordinate system of the seek operation.

pos
The pos field specified the pos when the seek is in absolute position.

round_down
For xy coordinate seeks, rounding down means that any x in the box of the character lands on that character. For instance when clicking rounding down is the user's expected behavior. Not rounding down means that the right hand portion of the character's box, which is closer to the next character, will land on that next character. The unrounded behavior is the expected behavior when moving vertically - and keeping the preferred x.

x
The x coordinate for xy type seeks.

y
The y coordinate for xy type seeks.

line
The line number of a line-character type seek.

character
The character number of a line-character type seek.

See Also
Buffer_Seek_Type
4coder_Buffer_Positioning_System

§3.4.36: Full_Cursor

struct Full_Cursor {
int32_t pos;
int32_t character_pos;
int32_t line;
int32_t character;
int32_t wrap_line;
float unwrapped_x;
float unwrapped_y;
float wrapped_x;
float wrapped_y;
};
Description
Full_Cursor describes the position of a cursor in every buffer + and keeping the preferred x.

x
The x coordinate for xy type seeks.

y
The y coordinate for xy type seeks.

line
The line number of a line-character type seek.

character
The character number of a line-character type seek.

See Also
Buffer_Seek_Type
4coder_Buffer_Positioning_System

§3.4.37: Full_Cursor

struct Full_Cursor {
int32_t pos;
int32_t character_pos;
int32_t line;
int32_t character;
int32_t wrap_line;
float unwrapped_x;
float unwrapped_y;
float wrapped_x;
float wrapped_y;
};
Description
Full_Cursor describes the position of a cursor in every buffer coordinate system supported by 4coder. This cursor type requires that the buffer is associated with a view to give the x/y values meaning.

Fields
pos
This field contains the cursor's position in absolute byte index positioning.

character_pos
This field contains the cursor's position in apparent character index positioning.

line
This field contains the number of the line where the cursor is located. This field is one based.

character
This field contains the number of the character from the beginninf of the line where the cursor is located. This field is one based.

wrap_line
This field contains the number of the line where the cursor is located, taking the line wrapping - into account. This field is one based.

unwrapped_x
This field contains the x position measured with unwrapped lines.

unwrapped_y
This field contains the y position measured with unwrapped lines.

wrapped_x
This field contains the x position measured with wrapped lines.

wrapped_y
This field contains the y position measured with wrapped lines.

See Also
4coder_Buffer_Positioning_System

§3.4.37: Partial_Cursor

struct Partial_Cursor {
int32_t pos;
int32_t line;
int32_t character;
};
Description
Partial_Cursor describes the position of a cursor in all of + into account. This field is one based.

unwrapped_x
This field contains the x position measured with unwrapped lines.

unwrapped_y
This field contains the y position measured with unwrapped lines.

wrapped_x
This field contains the x position measured with wrapped lines.

wrapped_y
This field contains the y position measured with wrapped lines.

See Also
4coder_Buffer_Positioning_System

§3.4.38: Partial_Cursor

struct Partial_Cursor {
int32_t pos;
int32_t line;
int32_t character;
};
Description
Partial_Cursor describes the position of a cursor in all of the coordinate systems that a invariant to the View. In other words the coordinate systems available here can be used on a buffer that is not currently associated with a View.

Fields
pos
This field contains the cursor's position in absolute byte index positioning.

line
This field contains the number of the character from the beginninf of the line - where the cursor is located. This field is one based.

character
This field contains the number of the column where the cursor is located. This field is one based.

See Also
4coder_Buffer_Positioning_System

§3.4.38: Buffer_Edit

struct Buffer_Edit {
int32_t str_start;
int32_t len;
int32_t start;
int32_t end;
};
Description
Buffer_Edit describes a range of a buffer and string to replace that range. + where the cursor is located. This field is one based.

character
This field contains the number of the column where the cursor is located. This field is one based.

See Also
4coder_Buffer_Positioning_System

§3.4.39: Buffer_Edit

struct Buffer_Edit {
int32_t str_start;
int32_t len;
int32_t start;
int32_t end;
};
Description
Buffer_Edit describes a range of a buffer and string to replace that range. A Buffer_Edit has to be paired with a string that contains the actual text that -will be replaced into the buffer.

Fields
str_start
The str_start field specifies the first character in the accompanying string that corresponds with this edit.

len
The len field specifies the length of the string being written into the buffer.

start
The start field specifies the start of the range in the buffer to replace in absolute position.

end
The end field specifies one past the end of the range in the buffer to replace in absolute position.


§3.4.39: Buffer_Summary

struct Buffer_Summary {
bool32 exists;
bool32 ready;
int32_t buffer_id;
Access_Flag lock_flags;
int32_t size;
int32_t line_count;
char * file_name;
int32_t file_name_len;
char * buffer_name;
int32_t buffer_name_len;
Dirty_State dirty;
bool32 is_lexed;
bool32 tokens_are_ready;
int32_t map_id;
bool32 unwrapped_lines;
};
Description
Buffer_Summary acts as a handle to a buffer and describes the state of the buffer.

Fields
exists
This field indicates whether the Buffer_Summary describes a buffer that is open in 4coder. +will be replaced into the buffer.

Fields
str_start
The str_start field specifies the first character in the accompanying string that corresponds with this edit.

len
The len field specifies the length of the string being written into the buffer.

start
The start field specifies the start of the range in the buffer to replace in absolute position.

end
The end field specifies one past the end of the range in the buffer to replace in absolute position.


§3.4.40: Buffer_Summary

struct Buffer_Summary {
bool32 exists;
bool32 ready;
int32_t buffer_id;
Access_Flag lock_flags;
int32_t size;
int32_t line_count;
char * file_name;
int32_t file_name_len;
char * buffer_name;
int32_t buffer_name_len;
Dirty_State dirty;
bool32 is_lexed;
bool32 tokens_are_ready;
int32_t map_id;
bool32 unwrapped_lines;
};
Description
Buffer_Summary acts as a handle to a buffer and describes the state of the buffer.

Fields
exists
This field indicates whether the Buffer_Summary describes a buffer that is open in 4coder. When this field is false the summary is referred to as a "null summary".

ready
If this is not a null summary, this field indicates whether the buffer has finished loading.

buffer_id
If this is not a null summary this field is the id of the associated buffer. If this is a null summary then buffer_id is 0.

lock_flags
If this is not a null summary, this field contains flags describing the protection status of the buffer.

size
If this is not a null summary, this field specifies the size of the text in the buffer.

line_count
If this is not a null summary, this field specifies the number of lines in the buffer.

file_name
If this is not a null summary, this field specifies the file name associated to this buffer.

file_name_len
This field specifies the length of the file_name string.

buffer_name
If this is not a null summary, this field specifies the name of the buffer.

buffer_name_len
This field specifies the length of the buffer_name string.

dirty
This field indicates the dirty state of the buffer.

is_lexed
If this is not a null summary, this field indicates whether the buffer is set to lex tokens.

tokens_are_ready
If this is not a null summary, this field indicates whether the buffer has up to date tokens available. If this field is false, it may simply mean the tokens are still being generated in a background task and will be available later. If that is the case, is_lexed will be true to indicate that the buffer is trying to get - it's tokens up to date.

map_id
If this is not a null summary, this field specifies the id of the command map for this buffer.

unwrapped_lines
If this is not a null summary, this field indicates whether the buffer 'prefers' wrapped lines.

See Also
Access_Flag
Dirty_State

§3.4.40: View_Summary

struct View_Summary {
bool32 exists;
int32_t view_id;
int32_t buffer_id;
Access_Flag lock_flags;
Full_Cursor cursor;
Full_Cursor mark;
float preferred_x;
float line_height;
bool32 unwrapped_lines;
bool32 show_whitespace;
i32_Rect file_region;
GUI_Scroll_Vars scroll_vars;
};
Description
View_Summary acts as a handle to a view and describes the state of the view.

Fields
exists
This field indicates whether the View_Summary describes a view that is open in 4coder. + it's tokens up to date.

map_id
If this is not a null summary, this field specifies the id of the command map for this buffer.

unwrapped_lines
If this is not a null summary, this field indicates whether the buffer 'prefers' wrapped lines.

See Also
Access_Flag
Dirty_State

§3.4.41: View_Summary

struct View_Summary {
bool32 exists;
int32_t view_id;
int32_t buffer_id;
Access_Flag lock_flags;
Full_Cursor cursor;
Full_Cursor mark;
float preferred_x;
float line_height;
bool32 unwrapped_lines;
bool32 show_whitespace;
i32_Rect file_region;
GUI_Scroll_Vars scroll_vars;
};
Description
View_Summary acts as a handle to a view and describes the state of the view.

Fields
exists
This field indicates whether the View_Summary describes a view that is open in 4coder. When this field is false the summary is referred to as a "null summary".

view_id
If this is not a null summary, this field is the id of the associated view. - If this is a null summary then view_id is 0.

buffer_id
If this is not a null summary, then this is the id of the buffer this view currently sees.

lock_flags
If this is not a null summary, this field contains flags describing the protection status of the view.

cursor
If this is not a null summary, this describes the position of the cursor.

mark
If this is not a null summary, this describes the position of the mark.

preferred_x
If this is not a null summary, this is the x position that is maintained in vertical navigation.

line_height
If this is not a null summary, this specifies the height of a line rendered in the view.

unwrapped_lines
If this is not a null summary, this indicates that the view is set to render with unwrapped lines.

show_whitespace
If this is not a null summary, this indicates that the view is set to highlight white space.

file_region
If this is not a null summary, this describes the screen position in which this view's buffer is displayed.

scroll_vars
If this is not a null summary, this describes the scrolling position inside the view.

See Also
Access_Flag
Full_Cursor

§3.4.41: User_Input

struct User_Input {
User_Input_Type_ID type;
bool32 abort;
union {
Key_Event_Data key;
Mouse_State mouse;
};
Generic_Command command;
};
Description
User_Input describes a user input event which can be either a key press or mouse event.

Fields
type
This field specifies whether the event was a key press or mouse event.

abort
This field indicates that an abort event has occurred and the command needs to shut down.

key
This field describes a key press event.

mouse
This field describes a mouse input event.

command
If this event would trigger a command, this field specifies what the command would be.

See Also
User_Input_Type_ID
Generic_Command

§3.4.42: Query_Bar

struct Query_Bar {
String prompt;
String string;
};
Description
Query_Bar is a struct used to store information in the user's control -that will be displayed as a drop down bar durring an interactive command.

Fields
prompt
This specifies the prompt portion of the drop down bar.

string
This specifies the main string portion of the drop down bar.


§3.4.43: Event_Message

struct Event_Message {
int32_t type;
};
Description
This feature is not implemented.

Fields
type
This feature is not implemented.


§3.4.44: Theme_Color

struct Theme_Color {
Style_Tag tag;
int_color color;
};
Description
Theme_Color stores a style tag/color pair, for the purpose of setting and getting colors in the theme.

Fields
tag
The style slot in the style palette.

color
The color in the slot.

See Also
Style_Tag
int_color

§3.4.45: Buffer_Batch_Edit_Type

enum Buffer_Batch_Edit_Type;
Description
A Buffer_Batch_Edit_Type is a type of batch operation.

Values
BatchEdit_Normal
The BatchEdit_Normal operation is always correct but does the most work if there are tokens to correct.

BatchEdit_PreserveTokens
The BatchEdit_PreserveTokens operation is one in which none of the edits add, delete, or change any tokens. - This usually applies when whitespace is being replaced with whitespace.


§3.4.46: Buffer_Batch_Edit

struct Buffer_Batch_Edit {
char * str;
int32_t str_len;
Buffer_Edit * edits;
int32_t edit_count;
};
Description
This struct is used to bundle the parameters of the buffer_batch_edit function. It is convenient + If this is a null summary then view_id is 0.

buffer_id
If this is not a null summary, then this is the id of the buffer this view currently sees.

lock_flags
If this is not a null summary, this field contains flags describing the protection status of the view.

cursor
If this is not a null summary, this describes the position of the cursor.

mark
If this is not a null summary, this describes the position of the mark.

preferred_x
If this is not a null summary, this is the x position that is maintained in vertical navigation.

line_height
If this is not a null summary, this specifies the height of a line rendered in the view.

unwrapped_lines
If this is not a null summary, this indicates that the view is set to render with unwrapped lines.

show_whitespace
If this is not a null summary, this indicates that the view is set to highlight white space.

file_region
If this is not a null summary, this describes the screen position in which this view's buffer is displayed.

scroll_vars
If this is not a null summary, this describes the scrolling position inside the view.

See Also
Access_Flag
Full_Cursor

§3.4.42: User_Input

struct User_Input {
User_Input_Type_ID type;
bool32 abort;
union {
Key_Event_Data key;
Mouse_State mouse;
};
Generic_Command command;
};
Description
User_Input describes a user input event which can be either a key press or mouse event.

Fields
type
This field specifies whether the event was a key press or mouse event.

abort
This field indicates that an abort event has occurred and the command needs to shut down.

key
This field describes a key press event.

mouse
This field describes a mouse input event.

command
If this event would trigger a command, this field specifies what the command would be.

See Also
User_Input_Type_ID
Generic_Command

§3.4.43: Query_Bar

struct Query_Bar {
String prompt;
String string;
};
Description
Query_Bar is a struct used to store information in the user's control +that will be displayed as a drop down bar durring an interactive command.

Fields
prompt
This specifies the prompt portion of the drop down bar.

string
This specifies the main string portion of the drop down bar.


§3.4.44: Event_Message

struct Event_Message {
int32_t type;
};
Description
This feature is not implemented.

Fields
type
This feature is not implemented.


§3.4.45: Theme_Color

struct Theme_Color {
Style_Tag tag;
int_color color;
};
Description
Theme_Color stores a style tag/color pair, for the purpose of setting and getting colors in the theme.

Fields
tag
The style slot in the style palette.

color
The color in the slot.

See Also
Style_Tag
int_color

§3.4.46: Buffer_Batch_Edit_Type

enum Buffer_Batch_Edit_Type;
Description
A Buffer_Batch_Edit_Type is a type of batch operation.

Values
BatchEdit_Normal
The BatchEdit_Normal operation is always correct but does the most work if there are tokens to correct.

BatchEdit_PreserveTokens
The BatchEdit_PreserveTokens operation is one in which none of the edits add, delete, or change any tokens. + This usually applies when whitespace is being replaced with whitespace.


§3.4.47: Buffer_Batch_Edit

struct Buffer_Batch_Edit {
char * str;
int32_t str_len;
Buffer_Edit * edits;
int32_t edit_count;
};
Description
This struct is used to bundle the parameters of the buffer_batch_edit function. It is convenient for a few functions that return a batch edit to the user.

Fields
str
The pointer to the edit string buffer.

str_len
The length of the edit string buffer.

edits
The array of edits to be applied.

edit_count
The number of edits in the array.

See Also
buffer_batch_edit

§4 String Library

§4.1 String Intro

Coming Soon

§4.2 String Function List

§4.3 String Function Descriptions

§4.3.1: char_is_slash

fstr_bool char_is_slash(
char c
)
Description
This call returns non-zero if c is \ or /.


§4.3.2: char_is_upper

fstr_bool char_is_upper(
char c
)
Description
If c is an uppercase letter this call returns true.


§4.3.3: char_is_lower

fstr_bool char_is_lower(
char c
)
Description
If c is a lower letter this call returns true.


§4.3.4: char_to_upper

char char_to_upper(
char c
)
Description
If c is a lowercase letter this call returns the uppercase equivalent, otherwise it returns c.


§4.3.5: char_to_lower

char char_to_lower(
char c
)
Description
If c is an uppercase letter this call returns the lowercase equivalent, otherwise it returns c.


§4.3.6: char_is_whitespace

fstr_bool char_is_whitespace(
char c
)
Description
This call returns non-zero if c is whitespace.


§4.3.7: char_is_alpha_numeric

fstr_bool char_is_alpha_numeric(
char c
)
Description
This call returns non-zero if c is any alphanumeric character including underscore.


§4.3.8: char_is_alpha_numeric_true

fstr_bool char_is_alpha_numeric_true(
char c
)
Description
This call returns non-zero if c is any alphanumeric character no including underscore.


§4.3.9: char_is_alpha

fstr_bool char_is_alpha(
char c
)
Description
This call returns non-zero if c is any alphabetic character including underscore.


§4.3.10: char_is_alpha_true

fstr_bool char_is_alpha_true(
char c
)
Description
This call returns non-zero if c is any alphabetic character.


§4.3.11: char_is_hex

fstr_bool char_is_hex(
char c
)
Description
This call returns non-zero if c is any valid hexadecimal digit.


§4.3.12: char_is_numeric

fstr_bool char_is_numeric(
char c
)
Description
This call returns non-zero if c is any valid decimal digit.


§4.3.13: make_string_cap

String make_string_cap(
void *str,
int32_t size,
int32_t mem_size
)
Parameters
str
The str parameter provides the of memory with which the string shall operate.
size
The size parameter expresses the initial size of the string. If the memory does not already contain a useful string this should be zero.
mem_size
The mem_size parameter expresses the full size of the memory provided by str.
Description
This call returns the String created from the parameters.


§4.3.14: make_string

String make_string(
void *str,
int32_t size
)
Parameters
str
The str parameter provides the of memory with which the string shall operate.
size
The size parameter expresses the initial size of the string. @@ -310,12 +310,8 @@ or in whitespace after the token.
See Also

§5.4.2: cpp_lex_step

Cpp_Lex_Result cpp_lex_step(
Cpp_Lex_Data *S_ptr,
char *chunk,
int32_t size,
int32_t full_size,
Cpp_Token_Array *token_array_out,
int32_t max_tokens_out
)
Parameters
S_ptr
The lexer state. Go to the Cpp_Lex_Data section to see how to initialize the state.
chunk
The first or next chunk of the file being lexed.
size
The number of bytes in the chunk including the null terminator if the chunk ends in a null terminator. -If the chunk ends in a null terminator the system will interpret it as the end of the file.
full_size
If the final chunk is not null terminated this parameter should specify the length of the -file in bytes. To rely on an eventual null terminator use HAS_NULL_TERM for this parameter.
token_array_out
The token array structure that will receive the tokens output by the lexer.
max_tokens_out
The maximum number of tokens to be output to the token array. To rely on the -max built into the token array pass NO_OUT_LIMIT here.
Description
This call is the primary interface of the lexing system. It is quite general so it can be used in -a lot of different ways. I will explain the general rules first, and then give some examples of common -ways it might be used.

+index can be -1 if the position is before the first token.

See Also

§5.4.2: cpp_lex_step

Cpp_Lex_Result cpp_lex_step(
Cpp_Lex_Data *S_ptr,
char *chunk,
int32_t size,
int32_t full_size,
Cpp_Token_Array *token_array_out,
int32_t max_tokens_out
)
Parameters
S_ptr
The lexer state. Go to the Cpp_Lex_Data section to see how to initialize the state.
chunk
The first or next chunk of the file being lexed.
size
The number of bytes in the chunk including the null terminator if the chunk ends in a null terminator. If the chunk ends in a null terminator the system will interpret it as the end of the file.
full_size
If the final chunk is not null terminated this parameter should specify the length of the file in bytes. To rely on an eventual null terminator use HAS_NULL_TERM for this parameter.
token_array_out
The token array structure that will receive the tokens output by the lexer.
max_tokens_out
The maximum number of tokens to be output to the token array. To rely on the +max built into the token array pass NO_OUT_LIMIT here.
Description
This call is the primary interface of the lexing system. It is quite general so it can be used in a lot of different ways. I will explain the general rules first, and then give some examples of common ways it might be used.

First a lexing state, Cpp_Lex_Data, must be initialized. The file to lex must be read into N contiguous chunks of memory. An output Cpp_Token_Array must be allocated and initialized with the appropriate count and max_count values. Then each chunk of the file must be passed to cpp_lex_step in order using the same lexing state for each call. diff --git a/4coder_auto_indent.cpp b/4coder_auto_indent.cpp index 76790477..94f2c7e5 100644 --- a/4coder_auto_indent.cpp +++ b/4coder_auto_indent.cpp @@ -511,7 +511,7 @@ get_indent_lines_whole_tokens(Application_Links *app, Buffer_Summary *buffer, Cp for (;line_start > 0;){ int32_t line_start_pos = 0; Cpp_Token *token = get_first_token_at_line(app, buffer, tokens, line_start, &line_start_pos); - if (token->start < line_start_pos){ + if (token && token->start < line_start_pos){ line_start = buffer_get_line_index(app, buffer, token->start); } else{ diff --git a/4coder_custom_api.h b/4coder_custom_api.h index b1e8075f..8bcfdd38 100644 --- a/4coder_custom_api.h +++ b/4coder_custom_api.h @@ -55,6 +55,7 @@ #define DIRECTORY_GET_HOT_SIG(n) int32_t n(Application_Links *app, char *out, int32_t capacity) #define GET_FILE_LIST_SIG(n) File_List n(Application_Links *app, char *dir, int32_t len) #define FREE_FILE_LIST_SIG(n) void n(Application_Links *app, File_List list) +#define SET_GUI_UP_DOWN_KEYS_SIG(n) void n(Application_Links *app, int16_t up_key, int16_t down_key) #define MEMORY_ALLOCATE_SIG(n) void* n(Application_Links *app, int32_t size) #define MEMORY_SET_PROTECTION_SIG(n) bool32 n(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags) #define MEMORY_FREE_SIG(n) void n(Application_Links *app, void *ptr, int32_t size) @@ -122,6 +123,7 @@ typedef GET_THEME_COLORS_SIG(Get_Theme_Colors_Function); typedef DIRECTORY_GET_HOT_SIG(Directory_Get_Hot_Function); typedef GET_FILE_LIST_SIG(Get_File_List_Function); typedef FREE_FILE_LIST_SIG(Free_File_List_Function); +typedef SET_GUI_UP_DOWN_KEYS_SIG(Set_GUI_Up_Down_Keys_Function); typedef MEMORY_ALLOCATE_SIG(Memory_Allocate_Function); typedef MEMORY_SET_PROTECTION_SIG(Memory_Set_Protection_Function); typedef MEMORY_FREE_SIG(Memory_Free_Function); @@ -191,6 +193,7 @@ Get_Theme_Colors_Function *get_theme_colors; Directory_Get_Hot_Function *directory_get_hot; Get_File_List_Function *get_file_list; Free_File_List_Function *free_file_list; +Set_GUI_Up_Down_Keys_Function *set_gui_up_down_keys; Memory_Allocate_Function *memory_allocate; Memory_Set_Protection_Function *memory_set_protection; Memory_Free_Function *memory_free; @@ -259,6 +262,7 @@ Get_Theme_Colors_Function *get_theme_colors_; Directory_Get_Hot_Function *directory_get_hot_; Get_File_List_Function *get_file_list_; Free_File_List_Function *free_file_list_; +Set_GUI_Up_Down_Keys_Function *set_gui_up_down_keys_; Memory_Allocate_Function *memory_allocate_; Memory_Set_Protection_Function *memory_set_protection_; Memory_Free_Function *memory_free_; @@ -335,6 +339,7 @@ app_links->get_theme_colors_ = Get_Theme_Colors;\ app_links->directory_get_hot_ = Directory_Get_Hot;\ app_links->get_file_list_ = Get_File_List;\ app_links->free_file_list_ = Free_File_List;\ +app_links->set_gui_up_down_keys_ = Set_GUI_Up_Down_Keys;\ app_links->memory_allocate_ = Memory_Allocate;\ app_links->memory_set_protection_ = Memory_Set_Protection;\ app_links->memory_free_ = Memory_Free;\ @@ -403,6 +408,7 @@ static inline void get_theme_colors(Application_Links *app, Theme_Color *colors, static inline int32_t directory_get_hot(Application_Links *app, char *out, int32_t capacity){return(app->directory_get_hot(app, out, capacity));} static inline File_List get_file_list(Application_Links *app, char *dir, int32_t len){return(app->get_file_list(app, dir, len));} static inline void free_file_list(Application_Links *app, File_List list){(app->free_file_list(app, list));} +static inline void set_gui_up_down_keys(Application_Links *app, int16_t up_key, int16_t down_key){(app->set_gui_up_down_keys(app, up_key, down_key));} static inline void* memory_allocate(Application_Links *app, int32_t size){return(app->memory_allocate(app, size));} static inline bool32 memory_set_protection(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags){return(app->memory_set_protection(app, ptr, size, flags));} static inline void memory_free(Application_Links *app, void *ptr, int32_t size){(app->memory_free(app, ptr, size));} @@ -471,6 +477,7 @@ static inline void get_theme_colors(Application_Links *app, Theme_Color *colors, static inline int32_t directory_get_hot(Application_Links *app, char *out, int32_t capacity){return(app->directory_get_hot_(app, out, capacity));} static inline File_List get_file_list(Application_Links *app, char *dir, int32_t len){return(app->get_file_list_(app, dir, len));} static inline void free_file_list(Application_Links *app, File_List list){(app->free_file_list_(app, list));} +static inline void set_gui_up_down_keys(Application_Links *app, int16_t up_key, int16_t down_key){(app->set_gui_up_down_keys_(app, up_key, down_key));} static inline void* memory_allocate(Application_Links *app, int32_t size){return(app->memory_allocate_(app, size));} static inline bool32 memory_set_protection(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags){return(app->memory_set_protection_(app, ptr, size, flags));} static inline void memory_free(Application_Links *app, void *ptr, int32_t size){(app->memory_free_(app, ptr, size));} diff --git a/4coder_default_bindings.cpp b/4coder_default_bindings.cpp index bc060812..fbfab126 100644 --- a/4coder_default_bindings.cpp +++ b/4coder_default_bindings.cpp @@ -124,9 +124,88 @@ CUSTOM_COMMAND_SIG(seek_whitespace_down_end_line){ exec_command(app, seek_end_of_line); } +static bool32 enable_code_wrapping = 1; +static int32_t default_wrap_width = 672; + HOOK_SIG(my_start){ init_memory(app); + { + FILE *file = fopen("config.4coder", "rb"); + if (file){ + Temp_Memory temp = begin_temp_memory(&global_part); + + fseek(file, 0, SEEK_END); + int32_t size = ftell(file); + char *mem = (char*)push_block(&global_part, size+1); + fseek(file, 0, SEEK_SET); + fread(mem, 1, size+1, file); + fclose(file); + + Cpp_Token_Array array; + array.count = 0; + array.max_count = (1 << 20)/sizeof(Cpp_Token); + array.tokens = push_array(&global_part, Cpp_Token, array.max_count); + + Cpp_Lex_Data S = cpp_lex_data_init(); + Cpp_Lex_Result result = cpp_lex_step(&S, mem, size, HAS_NULL_TERM, &array, NO_OUT_LIMIT); + + if (result == LexResult_Finished){ + + for (int32_t i = 0; i < array.count; ++i){ + int32_t read_setting_failed = 1; + Cpp_Token id_token = array.tokens[i]; + if (id_token.type == CPP_TOKEN_IDENTIFIER){ + ++i; + if (i < array.count){ + Cpp_Token eq_token = array.tokens[i]; + if (eq_token.type == CPP_TOKEN_EQEQ){ + ++i; + if (i < array.count){ + Cpp_Token val_token = array.tokens[i]; + { + ++i; + if (i < array.count){ + Cpp_Token semicolon_token = array.tokens[i]; + if (semicolon_token.type == CPP_TOKEN_SEMICOLON){ + read_setting_failed = 0; + + String id = make_string(mem + id_token.start, id_token.size); + + if (match(id, "enable_code_wrapping")){ + if (val_token.type == CPP_TOKEN_BOOLEAN_CONSTANT){ + String val = make_string(mem + val_token.start, val_token.size); + if (val.str[0] == 't'){ + enable_code_wrapping = 1; + } + else{ + enable_code_wrapping = 0; + } + } + } + } + } + } + } + } + } + } + + if (read_setting_failed){ + for (; i < array.count; ++i){ + Cpp_Token token = array.tokens[i]; + if (token.type == CPP_TOKEN_SEMICOLON){ + break; + } + } + } + } + } + + end_temp_memory(temp); + } + } + change_theme(app, literal("4coder")); change_font(app, literal("Liberation Sans"), true); @@ -135,6 +214,12 @@ HOOK_SIG(my_start){ exec_command(app, change_active_panel); exec_command(app, hide_scrollbar); + { + View_Summary view = get_active_view(app, AccessAll); + int32_t width = view.file_region.x1 - view.file_region.x0; + default_wrap_width = width - 40; + } + // Theme options: // "4coder" // "Handmade Hero" @@ -214,8 +299,13 @@ OPEN_FILE_HOOK_SIG(my_file_settings){ buffer_set_setting(app, &buffer, BufferSetting_Lex, treat_as_code); buffer_set_setting(app, &buffer, BufferSetting_WrapLine, wrap_lines); - buffer_set_setting(app, &buffer, BufferSetting_MapID, - (treat_as_code)?((int32_t)my_code_map):((int32_t)mapid_file)); + buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, default_wrap_width); + buffer_set_setting(app, &buffer, BufferSetting_MapID, (treat_as_code)?((int32_t)my_code_map):((int32_t)mapid_file)); + + if (treat_as_code && enable_code_wrapping && buffer.size < (1 << 20)){ + buffer_set_setting(app, &buffer, BufferSetting_WrapLine, 1); + buffer_set_setting(app, &buffer, BufferSetting_VirtualWhitespace, 1); + } // no meaning for return return(0); diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index fa595830..d87709e4 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -1354,16 +1354,14 @@ buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int32_ int32_t chunk_size = sizeof(chunk); Stream_Chunk stream = {0}; - int32_t no_hard; - int32_t still_looping; char at_pos; --pos; if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){ // Step 1: Find the first non-whitespace character // behind the current position. - still_looping = true; - do{ + int32_t still_looping = 1; + while (still_looping){ for (; pos >= stream.start; --pos){ at_pos = stream.data[pos]; if (!char_is_whitespace(at_pos)){ @@ -1371,7 +1369,7 @@ buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int32_ } } still_looping = backward_stream_chunk(&stream); - } while(still_looping); + } double_break_1:; // Step 2: Continue scanning backward, at each '\n' @@ -1379,7 +1377,7 @@ buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int32_ // no_hard to true, set it back to false if a // non-whitespace character is discovered before // the next '\n' - no_hard = false; + int32_t no_hard = false; while (still_looping){ for (; pos >= stream.start; --pos){ at_pos = stream.data[pos]; @@ -2119,15 +2117,11 @@ CUSTOM_COMMAND_SIG(delete_word){ CUSTOM_COMMAND_SIG(snipe_token_or_word){ uint32_t access = AccessOpen; - View_Summary view; - Buffer_Summary buffer; - int32_t pos1, pos2; + View_Summary view = get_active_view(app, access); + Buffer_Summary buffer = get_buffer(app, view.buffer_id, access); - view = get_active_view(app, access); - buffer = get_buffer(app, view.buffer_id, access); - - pos1 = buffer_boundary_seek(app, &buffer, view.cursor.pos, false, BoundaryToken | BoundaryWhitespace); - pos2 = buffer_boundary_seek(app, &buffer, pos1, true, BoundaryToken | BoundaryWhitespace); + int32_t pos1 = buffer_boundary_seek(app, &buffer, view.cursor.pos, false, BoundaryToken | BoundaryWhitespace); + int32_t pos2 = buffer_boundary_seek(app, &buffer, pos1, true, BoundaryToken | BoundaryWhitespace); Range range = make_range(pos1, pos2); buffer_replace_range(app, &buffer, range.start, range.end, 0, 0); diff --git a/4coder_types.h b/4coder_types.h index c159781a..2a0d0996 100644 --- a/4coder_types.h +++ b/4coder_types.h @@ -123,6 +123,18 @@ ENUM(int32_t, Event_Message_Type_ID){ EventMessage_CloseView }; +/* DOC(A Wrap_Indicator_Mode is used in the buffer setting BufferSetting_WrapIndicator to specify how to indicate that line has been wrapped.) */ +ENUM(int32_t, Wrap_Indicator_Mode){ + /* DOC(WrapIndicator_Hide tells the buffer rendering system not to put any indicator on wrapped lines.) */ + WrapIndicator_Hide, + + /* DOC(WrapIndicator_Show_After_Line tells the buffer rendering system to put a backslash indicator on wrapped lines right after the last character of the line.) */ + WrapIndicator_Show_After_Line, + + /* DOC(WrapIndicator_Show_At_Wrap_Edge tells the buffer rendering system to put a backslash indicator on wrapped lines aligned with the wrap position for that line.) */ + WrapIndicator_Show_At_Wrap_Edge, +}; + /* DOC(A Buffer_Setting_ID names a setting in a buffer.) */ ENUM(int32_t, Buffer_Setting_ID){ /* DOC(BufferSetting_Null is not a valid setting, it is reserved to detect errors.) */ @@ -145,6 +157,12 @@ ENUM(int32_t, Buffer_Setting_ID){ best behavior try to only set this setting once per frame, if possible.) */ BufferSetting_WrapPosition, + /* DOC(The BufferSetting_MinimumBaseWrapPosition setting is used to increase the with in pixels allotted to a line for wrapping, by setting a minimum position away from the base of the line. The base of a line is always 0, or the left hand side of the view, in text files. In code files the base of a line is the amount the line is shifted to the right due to brace nesting. This setting allows for deeply nested code to remain readable by ensuring lines deep in the nesting get some minimum base width which may be more wrapping space than the non base adjusted wrap position would have allowed. In any case where the (default wrapping position) is greater than (the base + minimum base position), the larger ) the default will still be used. */ + BufferSetting_MinimumBaseWrapPosition, + + /* DOC(The BufferSetting_WrapIndicator setting is used to specify how wrapped lines should be marked so the user can see that they have been wrapped. The value should be one of the values in the Wrap_Indicator_Mode enum.) DOC_SEE(Wrap_Indicator_Mode) */ + BufferSetting_WrapIndicator, + /* DOC(The BufferSetting_MapID setting specifies the id of the command map that should be active when a buffer is active.) */ BufferSetting_MapID, diff --git a/4cpp_lexer.h b/4cpp_lexer.h index 25020c72..cfa20e95 100644 --- a/4cpp_lexer.h +++ b/4cpp_lexer.h @@ -954,21 +954,15 @@ cpp_lex_nonalloc_no_null_out_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz #define NO_OUT_LIMIT ((int32_t)(-1)) FCPP_LINK Cpp_Lex_Result -cpp_lex_step(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size, int32_t full_size, - Cpp_Token_Array *token_array_out, int32_t max_tokens_out)/* +cpp_lex_step(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size, int32_t full_size, Cpp_Token_Array *token_array_out, int32_t max_tokens_out)/* DOC_PARAM(S_ptr, The lexer state. Go to the Cpp_Lex_Data section to see how to initialize the state.) DOC_PARAM(chunk, The first or next chunk of the file being lexed.) -DOC_PARAM(size, The number of bytes in the chunk including the null terminator if the chunk ends in a null terminator. -If the chunk ends in a null terminator the system will interpret it as the end of the file.) -DOC_PARAM(full_size, If the final chunk is not null terminated this parameter should specify the length of the -file in bytes. To rely on an eventual null terminator use HAS_NULL_TERM for this parameter.) +DOC_PARAM(size, The number of bytes in the chunk including the null terminator if the chunk ends in a null terminator. If the chunk ends in a null terminator the system will interpret it as the end of the file.) +DOC_PARAM(full_size, If the final chunk is not null terminated this parameter should specify the length of the file in bytes. To rely on an eventual null terminator use HAS_NULL_TERM for this parameter.) DOC_PARAM(token_array_out, The token array structure that will receive the tokens output by the lexer.) DOC_PARAM(max_tokens_out, The maximum number of tokens to be output to the token array. To rely on the max built into the token array pass NO_OUT_LIMIT here.) - -DOC(This call is the primary interface of the lexing system. It is quite general so it can be used in -a lot of different ways. I will explain the general rules first, and then give some examples of common -ways it might be used. +DOC(This call is the primary interface of the lexing system. It is quite general so it can be used in a lot of different ways. I will explain the general rules first, and then give some examples of common ways it might be used. First a lexing state, Cpp_Lex_Data, must be initialized. The file to lex must be read into N contiguous chunks of memory. An output Cpp_Token_Array must be allocated and initialized with the appropriate count and max_count diff --git a/4ed.cpp b/4ed.cpp index b3983af1..0d7569f3 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -1733,6 +1733,10 @@ App_Init_Sig(app_init){ vars->cli_processes.procs = push_array(partition, CLI_Process, max_children); vars->cli_processes.max = max_children; vars->cli_processes.count = 0; + + // NOTE(allen): init GUI keys + models->user_up_key = key_up; + models->user_down_key = key_down; } internal i32 diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 28d452bb..2aebafc1 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -787,6 +787,24 @@ DOC_SEE(Buffer_Setting_ID) } }break; + case BufferSetting_MinimumBaseWrapPosition: + { + i32 new_value = value; + if (new_value < 0){ + new_value = 0; + } + if (new_value != file->settings.minimum_base_display_width){ + i16 font_id = file->settings.font_id; + Render_Font *font = get_font_info(models->font_set, font_id)->font; + file_set_minimum_base_display_width_and_fix_cursor(system, models, file, new_value, (f32)font->height, font->advance_data); + } + }break; + + case BufferSetting_WrapIndicator: + { + file->settings.wrap_indicator = value; + }break; + case BufferSetting_MapID: { if (value == mapid_global){ @@ -2226,5 +2244,14 @@ DOC(After this call the file list passed in should not be read or written to.) system->set_file_list(&list, make_string(0, 0)); } +API_EXPORT void +Set_GUI_Up_Down_Keys(Application_Links *app, int16_t up_key, int16_t down_key) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + Models *models = cmd->models; + models->user_up_key = up_key; + models->user_down_key = down_key; +} + // BOTTOM diff --git a/4ed_app_models.h b/4ed_app_models.h index 59f61ad2..32017f1e 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -89,6 +89,9 @@ struct Models{ b32 keep_playing; Debug_Data debug; + + i16 user_up_key; + i16 user_down_key; }; // BOTTOM diff --git a/4ed_file.cpp b/4ed_file.cpp index 9644b18e..053957c4 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -92,6 +92,7 @@ struct Editing_File_Settings{ i32 base_map_id; i32 display_width; i32 minimum_base_display_width; + i32 wrap_indicator; b32 dos_write_mode; b32 virtual_white; i16 font_id; @@ -439,22 +440,21 @@ editing_file_zero(){ internal Editing_File* working_set_alloc(Working_Set *working_set){ Editing_File *result = 0; - File_Node *node; - Buffer_Slot_ID id; if (working_set->file_count < working_set->file_max){ - node = working_set->free_sentinel.next; + File_Node *node = working_set->free_sentinel.next; Assert(node != &working_set->free_sentinel); result = (Editing_File*)node; dll_remove(node); - id = result->id; + Buffer_Slot_ID id = result->id; *result = editing_file_zero(); result->id = id; result->unique_buffer_id = ++working_set->unique_file_counter; dll_insert(&working_set->used_sentinel, node); result->settings.display_width = working_set->default_display_width; result->settings.minimum_base_display_width = working_set->default_minimum_base_display_width; + result->settings.wrap_indicator = WrapIndicator_Show_At_Wrap_Edge; ++working_set->file_count; } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 551b9290..b6849f07 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -1861,6 +1861,12 @@ file_set_display_width_and_fix_cursor(System_Functions *system, Models *models, file_measure_wraps_and_fix_cursor(system, models, file, font_height, adv); } +internal void +file_set_minimum_base_display_width_and_fix_cursor(System_Functions *system, Models *models, Editing_File *file, i32 minimum_base_display_width, f32 font_height, f32 *adv){ + file->settings.minimum_base_display_width = minimum_base_display_width; + file_measure_wraps_and_fix_cursor(system, models, file, font_height, adv); +} + // // // @@ -4893,6 +4899,9 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su GUI_id scroll_context = {0}; scroll_context.id[1] = VUI_Interactive + ((u64)view->interaction << 32); + i16 user_up_key = models->user_up_key; + i16 user_down_key = models->user_down_key; + switch (view->interaction){ case IInt_Sys_File_List: { @@ -4954,9 +4963,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su if (gui_begin_list(target, id, view->list_i, 0, snap_into_view, &update)){ // TODO(allen): Allow me to handle key consumption correctly here! - gui_standard_list(target, id, &view->gui_scroll, - view->scroll_region, - &keys, &view->list_i, &update); + gui_standard_list(target, id, &view->gui_scroll, view->scroll_region, &keys, &view->list_i, &update, user_up_key, user_down_key); } begin_exhaustive_loop(&loop, hdir); @@ -5038,15 +5045,11 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su if (gui_scroll_was_activated(target, scroll_context)){ snap_into_view = 1; } - gui_begin_scrollable(target, scroll_context, view->gui_scroll, - 9 * view->line_height, show_scrollbar); + gui_begin_scrollable(target, scroll_context, view->gui_scroll, 9 * view->line_height, show_scrollbar); id.id[0] = (u64)(working_set) + 1; - if (gui_begin_list(target, id, view->list_i, - 0, snap_into_view, &update)){ - gui_standard_list(target, id, &view->gui_scroll, - view->scroll_region, - &keys, &view->list_i, &update); + if (gui_begin_list(target, id, view->list_i, 0, snap_into_view, &update)){ + gui_standard_list(target, id, &view->gui_scroll, view->scroll_region, &keys, &view->list_i, &update, user_up_key, user_down_key); } { @@ -5940,7 +5943,7 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target params.font_height = (f32)line_height; params.adv = advance_data; params.virtual_white = file->settings.virtual_white; - params.wrap_slashes = BRWrapSlash_Show_At_Wrap_Edge; + params.wrap_slashes = file->settings.wrap_indicator; Buffer_Render_State state = {0}; Buffer_Layout_Stop stop = {0}; diff --git a/4ed_gui.cpp b/4ed_gui.cpp index 4410e963..db53c229 100644 --- a/4ed_gui.cpp +++ b/4ed_gui.cpp @@ -1258,7 +1258,7 @@ gui_do_jump(GUI_Target *target, GUI_View_Jump jump, GUI_Scroll_Vars vars){ internal void gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars *vars, i32_Rect scroll_region, Key_Summary *keys, i32 *list_i, GUI_Item_Update *update, - i16 key_user_up = 0, i16 key_user_down = 0){ + i16 user_up_key, i16 user_down_key){ if (update->has_adjustment){ *list_i = update->adjustment_value; @@ -1276,10 +1276,10 @@ gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars *vars, i32_Rect for (i32 j = 0; j < keys->count; ++j){ i16 key = keys->keys[j].keycode; - if (key == key_up || key == key_user_up){ + if (key == user_up_key){ --*list_i; } - else if (key == key_down || key == key_user_down){ + else if (key == user_down_key){ ++*list_i; } else if (key == '\n' || key == '\t'){ diff --git a/TODO.txt b/TODO.txt index 2891744b..a51e2dc4 100644 --- a/TODO.txt +++ b/TODO.txt @@ -90,10 +90,8 @@ ; ; [X] query buffer font info ; [X] issues with drive letters -; [] ad hoc call for setting up/down keys for interactive screens -; [] option to not open *messages* every startup -; [] API docs have duplicate ids? -; [] miblo's various number editors +; [X] ad hoc call for setting up/down keys for interactive screens +; [X] miblo's various number editors ; [] decent options for indentation rules for text & presentation ; @@ -194,6 +192,8 @@ ; [] support full length unicode file names ; [] user file bar string +; [] option to not open *messages* every startup +; [] API docs have duplicate ids? ; [] API docs as text file ; [] read only files ; [] option to hide hidden files diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index 141bbacc..8a2ff23f 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -1188,12 +1188,6 @@ struct Buffer_Render_Params{ i32 wrap_slashes; }; -enum Wrap_Slash_Mode{ - BRWrapSlash_Hide, - BRWrapSlash_Show_After_Line, - BRWrapSlash_Show_At_Wrap_Edge, -}; - struct Buffer_Render_State{ Buffer_Stream_Type stream; b32 still_looping; @@ -1295,12 +1289,12 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 if (params.wrapped){ switch (params.wrap_slashes){ - case BRWrapSlash_Show_After_Line: + case WrapIndicator_Show_After_Line: { S.write = write_render_item(S.write, S.i-1, '\\', BRFlag_Ghost_Character); }break; - case BRWrapSlash_Show_At_Wrap_Edge: + case WrapIndicator_Show_At_Wrap_Edge: { if (S.write.x < shift_x + params.width){ S.write.x = shift_x + params.width; diff --git a/package.bat b/package.bat index 64ebd203..baaf09d7 100644 --- a/package.bat +++ b/package.bat @@ -1,47 +1,3 @@ @echo off -REM pushd W:\4ed\meta -REM cl %OPTS% ..\code\readme_generator.c /Fereadmegen -REM popd - -REM pushd W:\4ed\code - -REM ..\meta\readmegen - -REM call "build_all.bat" /O2 /DFRED_KEEP_ASSERT /Zi -REM del ..\current_dist\4coder\*.html -REM copy ..\build\4ed.exe ..\current_dist\4coder\* -REM copy ..\build\4ed.pdb ..\current_dist\4coder\* -REM copy ..\build\4ed_app.dll ..\current_dist\4coder\* -REM copy ..\build\4ed_app.pdb ..\current_dist\4coder\* -REM copy ..\data\* ..\current_dist\4coder\* -REM copy README.txt ..\current_dist\4coder\* -REM copy TODO.txt ..\current_dist\4coder\* -REM del ..\current_dist\4coder\.4coder_settings - -REM call "build_all.bat" /O2 /DFRED_SUPER /DFRED_KEEP_ASSERT /Zi -REM del ..\current_dist\4coder\*.html -REM copy ..\build\4ed.exe ..\current_dist_super\4coder\* -REM copy ..\build\4ed.pdb ..\current_dist_super\4coder\* -REM copy ..\build\4ed_app.dll ..\current_dist_super\4coder\* -REM copy ..\build\4ed_app.pdb ..\current_dist_super\4coder\* -REM copy buildsuper.bat ..\current_dist_super\4coder\* -REM copy ..\data\* ..\current_dist_super\4coder\* -REM del ..\current_dist_super\4coder\basic.cpp -REM copy 4coder_*.h ..\current_dist_super\4coder\* -REM copy 4coder_*.cpp ..\current_dist_super\4coder\* -REM copy README.txt ..\current_dist_super\4coder\* -REM copy TODO.txt ..\current_dist_super\4coder\* -REM copy ..\current_dist\4coder\3rdparty\* ..\current_dist_super\4coder\3rdparty\* -REM del ..\current_dist_super\4coder\*.lib -REM del ..\current_dist_super\4coder\*.obj -REM del ..\current_dist_super\4coder\4coder_custom.dll -REM del ..\current_dist_super\4coder\.4coder_settings - -REM copy 4coder_API.html ..\current_dist_super\* - -REM del ..\current_dist_power\power\* /F /Q -REM copy power\* ..\current_dist_power\power\* - -REM popd build.bat /DPACKAGE diff --git a/power/4coder_experiments.cpp b/power/4coder_experiments.cpp index eae0e1b3..770c1714 100644 --- a/power/4coder_experiments.cpp +++ b/power/4coder_experiments.cpp @@ -10,6 +10,8 @@ # define BIND_4CODER_TESTS(context) ((void)context) #endif +#include "4coder_miblo_numbers.cpp" + #include CUSTOM_COMMAND_SIG(kill_rect){ @@ -697,6 +699,13 @@ get_bindings(void *data, int size){ begin_map(context, mapid_file); bind(context, 'k', MDFR_ALT, kill_rect); bind(context, ' ', MDFR_ALT, multi_line_edit); + + bind(context, key_page_up, MDFR_ALT, miblo_increment_time_stamp); + bind(context, key_page_down, MDFR_ALT, miblo_decrement_time_stamp); + + bind(context, key_home, MDFR_ALT, miblo_increment_time_stamp_minute); + bind(context, key_end, MDFR_ALT, miblo_decrement_time_stamp_minute); + end_map(context); begin_map(context, my_code_map); diff --git a/power/4coder_miblo_numbers.cpp b/power/4coder_miblo_numbers.cpp new file mode 100644 index 00000000..15d53e07 --- /dev/null +++ b/power/4coder_miblo_numbers.cpp @@ -0,0 +1,381 @@ + +#if !defined(MIBLO_NUMBERS_4CODER) +#define MIBLO_NUMBERS_4CODER + +// TODO(allen): thevaber number converter idea + +static int32_t +get_numeric_string_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t start_pos, int32_t *numeric_start, int32_t *numeric_end){ + int32_t result = 0; + + char current = buffer_get_char(app, buffer, start_pos); + + if (char_is_numeric(current)){ + char chunk[1024]; + int32_t chunk_size = sizeof(chunk); + Stream_Chunk stream = {0}; + + int32_t pos = start_pos; + + int32_t pos1 = 0; + int32_t pos2 = 0; + + if (init_stream_chunk(&stream, app, buffer, start_pos, chunk, chunk_size)){ + + int32_t still_looping = 1; + while (still_looping){ + for (; pos >= stream.start; --pos){ + char at_pos = stream.data[pos]; + if (!char_is_numeric(at_pos)){ + ++pos; + goto double_break_1; + } + } + still_looping = backward_stream_chunk(&stream); + } + double_break_1:; + pos1 = pos; + + if (init_stream_chunk(&stream, app, buffer, start_pos, chunk, chunk_size)){ + + still_looping = 1; + while (still_looping){ + for (; pos < stream.end; ++pos){ + char at_pos = stream.data[pos]; + if (!char_is_numeric(at_pos)){ + goto double_break_2; + } + } + still_looping = forward_stream_chunk(&stream); + } + double_break_2:; + pos2 = pos; + + result = 1; + *numeric_start = pos1; + *numeric_end = pos2; + } + } + } + + return(result); +} + +struct Miblo_Number_Info{ + int32_t start, end; + int32_t x; +}; + +static int32_t +get_numeric_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t pos, Miblo_Number_Info *info){ + int32_t result = 0; + + int32_t numeric_start = 0, numeric_end = 0; + if (get_numeric_string_at_cursor(app, buffer, pos, &numeric_start, &numeric_end)){ + char numeric_string[1024]; + String str = make_string(numeric_string, numeric_end - numeric_start, sizeof(numeric_string)); + if (str.size < str.memory_size){ + buffer_read_range(app, buffer, numeric_start, numeric_end, numeric_string); + + int32_t x = str_to_int(str); + int_to_str(&str, x+1); + + info->start = numeric_start; + info->end = numeric_end; + info->x = x; + result = 1; + } + } + + return(result); +} + +CUSTOM_COMMAND_SIG(miblo_increment_basic){ + View_Summary view = get_active_view(app, AccessOpen); + Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); + + Miblo_Number_Info number = {0}; + if (get_numeric_at_cursor(app, &buffer, view.cursor.pos, &number)){ + char str_space[1024]; + String str = make_fixed_width_string(str_space); + int_to_str(&str, number.x + 1); + buffer_replace_range(app, &buffer, number.start, number.end, str.str, str.size); + view_set_cursor(app, &view, seek_pos(number.start + str.size - 1), 1); + } +} + +CUSTOM_COMMAND_SIG(miblo_decrement_basic){ + View_Summary view = get_active_view(app, AccessOpen); + Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); + + Miblo_Number_Info number = {0}; + if (get_numeric_at_cursor(app, &buffer, view.cursor.pos, &number)){ + char str_space[1024]; + String str = make_fixed_width_string(str_space); + int_to_str(&str, number.x - 1); + buffer_replace_range(app, &buffer, number.start, number.end, str.str, str.size); + view_set_cursor(app, &view, seek_pos(number.start + str.size - 1), 1); + } +} + +// NOTE(allen): miblo time stamp format +// (h+:)?m?m:ss + +static int32_t +get_timestamp_string_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t start_pos, int32_t *timestamp_start, int32_t *timestamp_end){ + int32_t result = 0; + + char current = buffer_get_char(app, buffer, start_pos); + + if (char_is_numeric(current) || current == ':'){ + char chunk[1024]; + int32_t chunk_size = sizeof(chunk); + Stream_Chunk stream = {0}; + + int32_t pos = start_pos; + + int32_t pos1 = 0; + int32_t pos2 = 0; + + if (init_stream_chunk(&stream, app, buffer, start_pos, chunk, chunk_size)){ + + int32_t still_looping = 1; + while (still_looping){ + for (; pos >= stream.start; --pos){ + char at_pos = stream.data[pos]; + if (!(char_is_numeric(at_pos) || at_pos == ':')){ + ++pos; + goto double_break_1; + } + } + still_looping = backward_stream_chunk(&stream); + } + double_break_1:; + pos1 = pos; + + if (init_stream_chunk(&stream, app, buffer, start_pos, chunk, chunk_size)){ + + still_looping = 1; + while (still_looping){ + for (; pos < stream.end; ++pos){ + char at_pos = stream.data[pos]; + if (!(char_is_numeric(at_pos) || at_pos == ':')){ + goto double_break_2; + } + } + still_looping = forward_stream_chunk(&stream); + } + double_break_2:; + pos2 = pos; + + result = 1; + *timestamp_start = pos1; + *timestamp_end = pos2; + } + } + } + + return(result); +} + +struct Miblo_Timestamp{ + int32_t hour, minute, second; +}; +static Miblo_Timestamp null_miblo_timestamp = {0}; + +enum{ + MIBLO_SECOND, + MIBLO_MINUTE, + MIBLO_HOUR +}; + +static Miblo_Timestamp +increment_timestamp(Miblo_Timestamp t, int32_t type, int32_t amt){ + Miblo_Timestamp r = t; + switch (type){ + case MIBLO_SECOND: + r.second += amt; + amt = 0; + + // TODO(allen): someday do the math, instead of being lazy. + while (r.second < 0){ + --amt; + r.second += 60; + } + + while (r.second >= 60){ + ++amt; + r.second -= 60; + } + + case MIBLO_MINUTE: + r.minute += amt; + amt = 0; + + // TODO(allen): someday do the math, instead of being lazy. + while (r.minute < 0){ + --amt; + r.minute += 60; + } + + while (r.minute >= 60){ + ++amt; + r.minute -= 60; + } + + case MIBLO_HOUR: + r.hour += amt; + } + + return(r); +} + +static void +timestamp_to_str(String *dest, Miblo_Timestamp t){ + dest->size = 0; + + if (t.hour > 0){ + append_int_to_str(dest, t.hour); + append(dest, ":"); + } + + if (t.minute >= 10){ + append_int_to_str(dest, t.minute); + } + else if (t.hour > 0){ + append(dest, "0"); + append_int_to_str(dest, t.minute); + } + else{ + append_int_to_str(dest, t.minute); + } + append(dest, ":"); + + if (t.second >= 10){ + append_int_to_str(dest, t.second); + } + else{ + append(dest, "0"); + append_int_to_str(dest, t.second); + } +} + +struct Miblo_Timestamp_Info{ + int32_t start, end; + Miblo_Timestamp time; +}; + +static int32_t +get_timestamp_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t pos, Miblo_Timestamp_Info *info){ + int32_t result = 0; + + int32_t timestamp_start = 0, timestamp_end = 0; + if (get_timestamp_string_at_cursor(app, buffer, pos, ×tamp_start, ×tamp_end)){ + char timestamp_string[1024]; + String str = make_string(timestamp_string, timestamp_end - timestamp_start, sizeof(timestamp_string)); + if (str.size < str.memory_size){ + buffer_read_range(app, buffer, timestamp_start, timestamp_end, timestamp_string); + + int32_t count_colons = 0; + for (int32_t i = 0; i < str.size; ++i){ + if (str.str[i] == ':'){ + ++count_colons; + } + } + + if (count_colons == 1 || count_colons == 2){ + Miblo_Timestamp t = {0}; + + int32_t success = 0; + + int32_t i = 0; + int32_t number_start[3], number_end[3]; + for (int32_t k = 0; k < 3; ++k){ + number_start[k] = i; + for (; i <= str.size; ++i){ + if (i == str.size || str.str[i] == ':'){ + number_end[k] = i; + break; + } + } + ++i; + if (i >= timestamp_end){ + break; + } + } + + if (count_colons == 2){ + t.hour = str_to_int(make_string(str.str + number_start[0], number_end[0] - number_start[0])); + + if (number_end[1] - number_start[1] == 2){ + + t.minute = str_to_int(make_string(str.str + number_start[1], number_end[1] - number_start[1])); + + if (number_end[2] - number_start[2] == 2){ + t.second = str_to_int(make_string(str.str + number_start[2], number_end[2] - number_start[2])); + + success = 1; + } + } + } + else{ + if (number_end[0] - number_start[0] == 2 || number_end[0] - number_start[0] == 1){ + t.minute = str_to_int(make_string(str.str + number_start[0], number_end[0] - number_start[0])); + + if (number_end[1] - number_start[1] == 2){ + t.second = str_to_int(make_string(str.str + number_start[1], number_end[1] - number_start[1])); + + success = 1; + } + } + } + + if (success){ + info->start = timestamp_start; + info->end = timestamp_end; + info->time = t; + result = 1; + } + } + } + } + + return(result); +} + +static void +miblo_time_stamp_alter(Application_Links *app, int32_t unit_type, int32_t amt){ + View_Summary view = get_active_view(app, AccessOpen); + Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); + + Miblo_Timestamp_Info timestamp = {0}; + if (get_timestamp_at_cursor(app, &buffer, view.cursor.pos, ×tamp)){ + char str_space[1024]; + String str = make_fixed_width_string(str_space); + + Miblo_Timestamp inc_timestamp = increment_timestamp(timestamp.time, unit_type, amt); + timestamp_to_str(&str, inc_timestamp); + buffer_replace_range(app, &buffer, timestamp.start, timestamp.end, str.str, str.size); + view_set_cursor(app, &view, seek_pos(timestamp.start + str.size - 1), 1); + } +} + +CUSTOM_COMMAND_SIG(miblo_increment_time_stamp){ + miblo_time_stamp_alter(app, MIBLO_SECOND, 1); +} + +CUSTOM_COMMAND_SIG(miblo_decrement_time_stamp){ + miblo_time_stamp_alter(app, MIBLO_SECOND, -1); +} + +CUSTOM_COMMAND_SIG(miblo_increment_time_stamp_minute){ + miblo_time_stamp_alter(app, MIBLO_MINUTE, 1); +} + +CUSTOM_COMMAND_SIG(miblo_decrement_time_stamp_minute){ + miblo_time_stamp_alter(app, MIBLO_MINUTE, -1); +} + +#endif + +