move towards searching commands custom side and custom allocator

This commit is contained in:
Allen Webster 2016-07-10 01:49:11 -04:00
parent 8f8f7ed5fd
commit c479e14f25
18 changed files with 1559 additions and 849 deletions

View File

@ -22,7 +22,7 @@ ul { list-style: none; padding: 0; margin: 0; }
<h2 id='section_introduction'>&sect;1 Introduction</h2>
<div>
<p>
This is the documentation for alpha 4.0.9 super! 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. </p>
This is the documentation for alpha 4.0.10 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. </p>
<p>
If you have questions or discover errors please contact <span style='font-family: "Courier New", Courier, monospace; text-align: left;'>editor@4coder.net</span> or to get help from community members you can post on the 4coder forums hosted on handmade.network at <span style='font-family: "Courier New", Courier, monospace; text-align: left;'>4coder.handmade.network</span></p>
</div>
@ -34,9 +34,13 @@ Coming Soon</i><div>
<ul>
<li><a href='#exec_command_doc'>exec_command</a></li>
<li><a href='#exec_system_command_doc'>exec_system_command</a></li>
<li><a href='#memory_alloc_doc'>memory_alloc</a></li>
<li><a href='#memory_set_protection_doc'>memory_set_protection</a></li>
<li><a href='#memory_free_doc'>memory_free</a></li>
<li><a href='#clipboard_post_doc'>clipboard_post</a></li>
<li><a href='#clipboard_count_doc'>clipboard_count</a></li>
<li><a href='#clipboard_index_doc'>clipboard_index</a></li>
<li><a href='#get_buffer_count_doc'>get_buffer_count</a></li>
<li><a href='#get_buffer_first_doc'>get_buffer_first</a></li>
<li><a href='#get_buffer_next_doc'>get_buffer_next</a></li>
<li><a href='#get_buffer_doc'>get_buffer</a></li>
@ -101,6 +105,7 @@ Coming Soon</i><div>
<li><a href='#Buffer_Seek_Type_doc'>Buffer_Seek_Type</a></li>
<li><a href='#View_Split_Position_doc'>View_Split_Position</a></li>
<li><a href='#Key_Modifier_Flag_doc'>Key_Modifier_Flag</a></li>
<li><a href='#Memory_Protect_Flags_doc'>Memory_Protect_Flags</a></li>
<li><a href='#Buffer_Create_Flag_doc'>Buffer_Create_Flag</a></li>
<li><a href='#Buffer_Kill_Flag_doc'>Buffer_Kill_Flag</a></li>
<li><a href='#Access_Flag_doc'>Access_Flag</a></li>
@ -181,8 +186,26 @@ If the buffer is not already in an open view and the view parameter is not NULL,
then the provided view will display the output buffer.
If the view parameter is NULL, no view will switch to the output.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Identifier_doc'>Buffer_Identifier</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Command_Line_Input_Flag_doc'>Command_Line_Input_Flag</a></div></div><hr>
<div id='memory_alloc_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.3: memory_alloc</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void* app->memory_alloc(
<div style='margin-left: 4mm;'>Application_Links *app,<br>int32_t size<br></div>)
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>TODO</div></div><hr>
<div id='memory_set_protection_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.4: memory_set_protection</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>int32_t app->memory_set_protection(
<div style='margin-left: 4mm;'>Application_Links *app,<br>void *ptr,<br>int32_t size,<br>Memory_Protect_Flags flags<br></div>)
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>TODO</div></div><hr>
<div id='memory_free_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.5: memory_free</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->memory_free(
<div style='margin-left: 4mm;'>Application_Links *app,<br>void *mem<br></div>)
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>TODO</div></div><hr>
<div id='clipboard_post_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.3: clipboard_post</h4>
<h4>&sect;3.3.6: clipboard_post</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->clipboard_post(
<div style='margin-left: 4mm;'>Application_Links *app,<br>int32_t clipboard_id,<br>char *str,<br>int32_t len<br></div>)
</div>
@ -202,7 +225,7 @@ If the view parameter is NULL, no view will switch to the output.</div><div styl
Also reports the copy to the operating system, so that it may
be pasted into other applications.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#The_4coder_Clipboard_doc'>The_4coder_Clipboard</a></div></div><hr>
<div id='clipboard_count_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.4: clipboard_count</h4>
<h4>&sect;3.3.7: clipboard_count</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>int32_t app->clipboard_count(
<div style='margin-left: 4mm;'>Application_Links *app,<br>int32_t clipboard_id<br></div>)
</div>
@ -212,7 +235,7 @@ be pasted into other applications.</div><div style='margin-top: 3mm; margin-bott
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns the number of items in the clipboard.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#The_4coder_Clipboard_doc'>The_4coder_Clipboard</a></div></div><hr>
<div id='clipboard_index_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.5: clipboard_index</h4>
<h4>&sect;3.3.8: clipboard_index</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>int32_t app->clipboard_index(
<div style='margin-left: 4mm;'>Application_Links *app,<br>int32_t clipboard_id,<br>int32_t item_index,<br>char *out,<br>int32_t len<br></div>)
</div>
@ -235,8 +258,14 @@ be pasted into other applications.</div><div style='margin-top: 3mm; margin-bott
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns the size of the item associated with item_index.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This function always returns the size of the item even if the output buffer is NULL.
If the output buffer is too small to contain the whole string, it is filled with the
first len character of the clipboard contents. The output string is not null terminated.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#The_4coder_Clipboard_doc'>The_4coder_Clipboard</a></div></div><hr>
<div id='get_buffer_count_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.9: get_buffer_count</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>int32_t app->get_buffer_count(
<div style='margin-left: 4mm;'>Application_Links *app<br></div>)
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>TODO</div></div><hr>
<div id='get_buffer_first_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.6: get_buffer_first</h4>
<h4>&sect;3.3.10: get_buffer_first</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>Buffer_Summary app->get_buffer_first(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Access_Flag access<br></div>)
</div>
@ -249,7 +278,7 @@ first len character of the clipboard contents. The output string is not null te
If the buffer returned does not exist, the loop is finished.
Buffers should not be killed durring a buffer loop.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#get_buffer_next_doc'>get_buffer_next</a></div></div><hr>
<div id='get_buffer_next_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.7: get_buffer_next</h4>
<h4>&sect;3.3.11: get_buffer_next</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->get_buffer_next(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Summary *buffer,<br>Access_Flag access<br></div>)
</div>
@ -267,7 +296,7 @@ The global buffer order is kept roughly in the order of most recently used to le
If the buffer outputted does not exist, the loop is finished.
Buffers should not be killed or created durring a buffer loop.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#get_buffer_first_doc'>get_buffer_first</a></div></div><hr>
<div id='get_buffer_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.8: get_buffer</h4>
<h4>&sect;3.3.12: get_buffer</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>Buffer_Summary app->get_buffer(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_ID buffer_id,<br>Access_Flag access<br></div>)
</div>
@ -281,7 +310,7 @@ Buffers should not be killed or created durring a buffer loop.</div><div style='
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns a summary that describes the indicated buffer if it exists and is accessible.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_ID_doc'>Buffer_ID</a></div></div><hr>
<div id='get_buffer_by_name_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.9: get_buffer_by_name</h4>
<h4>&sect;3.3.13: get_buffer_by_name</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>Buffer_Summary app->get_buffer_by_name(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *name,<br>int32_t len,<br>Access_Flag access<br></div>)
</div>
@ -299,7 +328,7 @@ Buffers should not be killed or created durring a buffer loop.</div><div style='
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns a summary that describes the indicated buffer if it exists and is accessible.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div></div><hr>
<div id='buffer_boundary_seek_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.10: buffer_boundary_seek</h4>
<h4>&sect;3.3.14: buffer_boundary_seek</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>int32_t app->buffer_boundary_seek(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Summary *buffer,<br>int32_t start_pos,<br>bool32 seek_forward,<br>Seek_Boundary_Flag flags<br></div>)
</div>
@ -323,7 +352,7 @@ Buffers should not be killed or created durring a buffer loop.</div><div style='
If the seek goes below 0 the returned value is -1.
If the seek goes past the end the returned value is the size of the buffer.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Seek_Boundary_Flag_doc'>Seek_Boundary_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#4coder_Buffer_Positioning_System_doc'>4coder_Buffer_Positioning_System</a></div></div><hr>
<div id='buffer_read_range_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.11: buffer_read_range</h4>
<h4>&sect;3.3.15: buffer_read_range</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->buffer_read_range(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Summary *buffer,<br>int32_t start,<br>int32_t end,<br>char *out<br></div>)
</div>
@ -349,7 +378,7 @@ The output is not null terminated.
This call fails if the buffer does not exist,
or if the read range is not within the bounds of the buffer.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#4coder_Buffer_Positioning_System_doc'>4coder_Buffer_Positioning_System</a></div></div><hr>
<div id='buffer_replace_range_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.12: buffer_replace_range</h4>
<h4>&sect;3.3.16: buffer_replace_range</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->buffer_replace_range(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Summary *buffer,<br>int32_t start,<br>int32_t end,<br>char *str,<br>int32_t len<br></div>)
</div>
@ -382,7 +411,7 @@ from start to end.
This call fails if the buffer does not exist, or if the replace
range is not within the bounds of the buffer.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#4coder_Buffer_Positioning_System_doc'>4coder_Buffer_Positioning_System</a></div></div><hr>
<div id='buffer_batch_edit_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.13: buffer_batch_edit</h4>
<h4>&sect;3.3.17: buffer_batch_edit</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->buffer_batch_edit(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Summary *buffer,<br>char *str,<br>int32_t str_len,<br>Buffer_Edit *edits,<br>int32_t edit_count,<br>Buffer_Batch_Edit_Type type<br></div>)
</div>
@ -406,9 +435,9 @@ range is not within the bounds of the buffer.</div><div style='margin-top: 3mm;
<div style='font-weight: 600;'>type</div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'>This prameter specifies what type of batch edit to execute.</div></div>
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero if the batch edit succeeds.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Edit_doc'>Buffer_Edit</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Batch_Edit_Type_doc'>Buffer_Batch_Edit_Type</a></div></div><hr>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero if the batch edit succeeds.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>TODO</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Edit_doc'>Buffer_Edit</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Batch_Edit_Type_doc'>Buffer_Batch_Edit_Type</a></div></div><hr>
<div id='buffer_set_setting_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.14: buffer_set_setting</h4>
<h4>&sect;3.3.18: buffer_set_setting</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->buffer_set_setting(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Summary *buffer,<br>Buffer_Setting_ID setting,<br>int32_t value<br></div>)
</div>
@ -426,7 +455,7 @@ range is not within the bounds of the buffer.</div><div style='margin-top: 3mm;
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Setting_ID_doc'>Buffer_Setting_ID</a></div></div><hr>
<div id='buffer_auto_indent_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.15: buffer_auto_indent</h4>
<h4>&sect;3.3.19: buffer_auto_indent</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->buffer_auto_indent(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Summary *buffer,<br>int32_t start,<br>int32_t end,<br>int32_t tab_width,<br>Auto_Indent_Flag flags<br></div>)
</div>
@ -455,7 +484,7 @@ start to end by inserting spaces or tabs at the beginning of the lines.
If the buffer does not have lexing enabled or the lexing job has not
completed this function will fail.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Auto_Indent_Flag_doc'>Auto_Indent_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#4coder_Buffer_Positioning_System_doc'>4coder_Buffer_Positioning_System</a></div></div><hr>
<div id='create_buffer_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.16: create_buffer</h4>
<h4>&sect;3.3.20: create_buffer</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>Buffer_Summary app->create_buffer(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *filename,<br>int32_t filename_len,<br>Buffer_Create_Flag flags<br></div>)
</div>
@ -477,7 +506,7 @@ If the buffer does not exist a new buffer is created and named after the given f
the filename corresponds to a file on the disk that file is loaded and put into buffer, if
the filename does not correspond to a file on disk the buffer is created empty.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Create_Flag_doc'>Buffer_Create_Flag</a></div></div><hr>
<div id='save_buffer_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.17: save_buffer</h4>
<h4>&sect;3.3.21: save_buffer</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->save_buffer(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Summary *buffer,<br>char *filename,<br>int32_t filename_len,<br>uint32_t flags<br></div>)
</div>
@ -499,7 +528,7 @@ the filename does not correspond to a file on disk the buffer is created empty.<
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero on success.</div></div><hr>
<div id='kill_buffer_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.18: kill_buffer</h4>
<h4>&sect;3.3.22: kill_buffer</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->kill_buffer(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Buffer_Identifier buffer,<br>View_ID view_id,<br>Buffer_Kill_Flag flags<br></div>)
</div>
@ -519,7 +548,7 @@ the filename does not correspond to a file on disk the buffer is created empty.<
dialogue needs to be displayed the provided view is used to show the dialogue.
If the view is not open the kill fails.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Kill_Flag_doc'>Buffer_Kill_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Identifier_doc'>Buffer_Identifier</a></div></div><hr>
<div id='get_view_first_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.19: get_view_first</h4>
<h4>&sect;3.3.23: get_view_first</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>View_Summary app->get_view_first(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Access_Flag access<br></div>)
</div>
@ -532,7 +561,7 @@ If the view is not open the kill fails.</div><div style='margin-top: 3mm; margin
If the View_Summary returned is a null summary, the loop is finished.
Views should not be closed or opened durring a view loop.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#get_view_next_doc'>get_view_next</a></div></div><hr>
<div id='get_view_next_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.20: get_view_next</h4>
<h4>&sect;3.3.24: get_view_next</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->get_view_next(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>Access_Flag access<br></div>)
</div>
@ -549,7 +578,7 @@ Views should not be closed or opened durring a view loop.</div><div style='margi
If the view outputted does not exist, the loop is finished.
Views should not be closed or opened durring a view loop.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#get_view_first_doc'>get_view_first</a></div></div><hr>
<div id='get_view_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.21: get_view</h4>
<h4>&sect;3.3.25: get_view</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>View_Summary app->get_view(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_ID view_id,<br>Access_Flag access<br></div>)
</div>
@ -563,7 +592,7 @@ Views should not be closed or opened durring a view loop.</div><div style='margi
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns a summary that describes the indicated view if it is open and accessible.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div></div><hr>
<div id='get_active_view_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.22: get_active_view</h4>
<h4>&sect;3.3.26: get_active_view</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>View_Summary app->get_active_view(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Access_Flag access<br></div>)
</div>
@ -573,7 +602,7 @@ Views should not be closed or opened durring a view loop.</div><div style='margi
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns a summary that describes the active view.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#set_active_view_doc'>set_active_view</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div></div><hr>
<div id='open_view_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.23: open_view</h4>
<h4>&sect;3.3.27: open_view</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>View_Summary app->open_view(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view_location,<br>View_Split_Position position<br></div>)
</div>
@ -589,7 +618,7 @@ Views should not be closed or opened durring a view loop.</div><div style='margi
returns a null summary.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>4coder is built with a limit of 16 views. If 16 views are already open when this is called the
call will fail.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#View_Split_Position_doc'>View_Split_Position</a></div></div><hr>
<div id='close_view_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.24: close_view</h4>
<h4>&sect;3.3.28: close_view</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->close_view(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view<br></div>)
</div>
@ -602,7 +631,7 @@ If the given view is the active view, the next active view in the global
order of view will be made active.
If the given view is the last open view in the system, the call will fail.</div></div><hr>
<div id='set_active_view_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.25: set_active_view</h4>
<h4>&sect;3.3.29: set_active_view</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->set_active_view(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view<br></div>)
</div>
@ -614,7 +643,7 @@ If the given view is the last open view in the system, the call will fail.</div>
active view, and takes subsequent commands and is returned
from get_active_view.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#get_active_view_doc'>get_active_view</a></div></div><hr>
<div id='view_set_setting_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.26: view_set_setting</h4>
<h4>&sect;3.3.30: view_set_setting</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->view_set_setting(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>View_Setting_ID setting,<br>int32_t value<br></div>)
</div>
@ -632,7 +661,7 @@ from get_active_view.</div><div style='margin-top: 3mm; margin-bottom: 3mm; colo
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero on success.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#View_Setting_ID_doc'>View_Setting_ID</a></div></div><hr>
<div id='view_set_split_proportion_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.27: view_set_split_proportion</h4>
<h4>&sect;3.3.31: view_set_split_proportion</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->view_set_split_proportion(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>float t<br></div>)
</div>
@ -646,7 +675,7 @@ from get_active_view.</div><div style='margin-top: 3mm; margin-bottom: 3mm; colo
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero on success.</div></div><hr>
<div id='view_compute_cursor_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.28: view_compute_cursor</h4>
<h4>&sect;3.3.32: view_compute_cursor</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->view_compute_cursor(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>Buffer_Seek seek,<br>Full_Cursor *cursor_out<br></div>)
</div>
@ -664,7 +693,7 @@ from get_active_view.</div><div style='margin-top: 3mm; margin-bottom: 3mm; colo
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero on success.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>Computes a Full_Cursor for the given seek position with no side effects.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Seek_doc'>Buffer_Seek</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Full_Cursor_doc'>Full_Cursor</a></div></div><hr>
<div id='view_set_cursor_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.29: view_set_cursor</h4>
<h4>&sect;3.3.33: view_set_cursor</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->view_set_cursor(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>Buffer_Seek seek,<br>bool32 set_preferred_x<br></div>)
</div>
@ -684,7 +713,7 @@ from get_active_view.</div><div style='margin-top: 3mm; margin-bottom: 3mm; colo
unless the change in cursor position is is a vertical motion that tries to keep the
cursor in the same column or x position.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Seek_doc'>Buffer_Seek</a></div></div><hr>
<div id='view_set_mark_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.30: view_set_mark</h4>
<h4>&sect;3.3.34: view_set_mark</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->view_set_mark(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>Buffer_Seek seek<br></div>)
</div>
@ -698,7 +727,7 @@ cursor in the same column or x position.</div><div style='margin-top: 3mm; margi
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero on success.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call sets the the view's mark position.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Seek_doc'>Buffer_Seek</a></div></div><hr>
<div id='view_set_highlight_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.31: view_set_highlight</h4>
<h4>&sect;3.3.35: view_set_highlight</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->view_set_highlight(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>int32_t start,<br>int32_t end,<br>bool32 turn_on<br></div>)
</div>
@ -723,7 +752,7 @@ is set to true the highlight will be shown and the cursor will be hidden. After
that either setting the with view_set_cursor or calling view_set_highlight and
the turn_on set to false, will switch back to showing the cursor.</div></div><hr>
<div id='view_set_buffer_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.32: view_set_buffer</h4>
<h4>&sect;3.3.36: view_set_buffer</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->view_set_buffer(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>Buffer_ID buffer_id,<br>Set_Buffer_Flag flags<br></div>)
</div>
@ -742,7 +771,7 @@ the turn_on set to false, will switch back to showing the cursor.</div></div><hr
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero on success.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>On success view_set_buffer sets the specified view's current buffer and
cancels and dialogue shown in the view and displays the file.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Set_Buffer_Flag_doc'>Set_Buffer_Flag</a></div></div><hr>
<div id='view_post_fade_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.33: view_post_fade</h4>
<h4>&sect;3.3.37: view_post_fade</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->view_post_fade(
<div style='margin-left: 4mm;'>Application_Links *app,<br>View_Summary *view,<br>float seconds,<br>int32_t start,<br>int32_t end,<br>int_color color<br></div>)
</div>
@ -768,7 +797,7 @@ cancels and dialogue shown in the view and displays the file.</div><div style='m
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero on success.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#int_color_doc'>int_color</a></div></div><hr>
<div id='get_user_input_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.34: get_user_input</h4>
<h4>&sect;3.3.38: get_user_input</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>User_Input app->get_user_input(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Input_Type_Flag get_type,<br>Input_Type_Flag abort_type<br></div>)
</div>
@ -786,19 +815,19 @@ command is executed an abort signal is returned. If an abort signal is ever ret
command should finish execution without any more calls that preempt the command.
If a get condition is met the user input is returned.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Input_Type_Flag_doc'>Input_Type_Flag</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#User_Input_doc'>User_Input</a></div></div><hr>
<div id='get_command_input_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.35: get_command_input</h4>
<h4>&sect;3.3.39: get_command_input</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>User_Input app->get_command_input(
<div style='margin-left: 4mm;'>Application_Links *app<br></div>)
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns the input that triggered the currently executing command.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#User_Input_doc'>User_Input</a></div></div><hr>
<div id='get_mouse_state_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.36: get_mouse_state</h4>
<h4>&sect;3.3.40: get_mouse_state</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>Mouse_State app->get_mouse_state(
<div style='margin-left: 4mm;'>Application_Links *app<br></div>)
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns the current mouse state as of the beginning of the frame.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Mouse_State_doc'>Mouse_State</a></div></div><hr>
<div id='start_query_bar_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.37: start_query_bar</h4>
<h4>&sect;3.3.41: start_query_bar</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->start_query_bar(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Query_Bar *bar,<br>uint32_t flags<br></div>)
</div>
@ -818,7 +847,7 @@ can be changed after the call to start_query_bar and the query bar shown by 4cod
will reflect the change. Since the bar stops showing when the command exits the
only use for this call is in an interactive command that makes calls to get_user_input.</div></div><hr>
<div id='end_query_bar_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.38: end_query_bar</h4>
<h4>&sect;3.3.42: end_query_bar</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->end_query_bar(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Query_Bar *bar,<br>uint32_t flags<br></div>)
</div>
@ -832,7 +861,7 @@ only use for this call is in an interactive command that makes calls to get_user
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>Stops showing the particular query bar specified by the bar parameter.</div></div><hr>
<div id='print_message_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.39: print_message</h4>
<h4>&sect;3.3.43: print_message</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->print_message(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *str,<br>int32_t len<br></div>)
</div>
@ -846,7 +875,7 @@ only use for this call is in an interactive command that makes calls to get_user
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call posts a string to the *messages* buffer.</div></div><hr>
<div id='change_theme_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.40: change_theme</h4>
<h4>&sect;3.3.44: change_theme</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->change_theme(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *name,<br>int32_t len<br></div>)
</div>
@ -860,7 +889,7 @@ only use for this call is in an interactive command that makes calls to get_user
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call changes 4coder's theme to one of the built in themes.</div></div><hr>
<div id='change_font_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.41: change_font</h4>
<h4>&sect;3.3.45: change_font</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->change_font(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *name,<br>int32_t len<br></div>)
</div>
@ -874,7 +903,7 @@ only use for this call is in an interactive command that makes calls to get_user
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call changes 4coder's font to one of the built in fonts.</div></div><hr>
<div id='set_theme_colors_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.42: set_theme_colors</h4>
<h4>&sect;3.3.46: set_theme_colors</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->set_theme_colors(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Theme_Color *colors,<br>int32_t count<br></div>)
</div>
@ -890,7 +919,7 @@ only use for this call is in an interactive command that makes calls to get_user
struct's tag is set to the color code in the struct. If the tag value is invalid
no change is made to the color pallet.</div></div><hr>
<div id='get_theme_colors_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.43: get_theme_colors</h4>
<h4>&sect;3.3.47: get_theme_colors</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->get_theme_colors(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Theme_Color *colors,<br>int32_t count<br></div>)
</div>
@ -906,7 +935,7 @@ no change is made to the color pallet.</div></div><hr>
color from the slot in the main color pallet specified by the tag. If the tag
value is invalid the color is filled with black.</div></div><hr>
<div id='directory_get_hot_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.44: directory_get_hot</h4>
<h4>&sect;3.3.48: directory_get_hot</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>int32_t app->directory_get_hot(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *out,<br>int32_t capacity<br></div>)
</div>
@ -924,7 +953,7 @@ 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.</div></div><hr>
<div id='get_file_list_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.45: get_file_list</h4>
<h4>&sect;3.3.49: get_file_list</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>File_List app->get_file_list(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *dir,<br>int32_t len<br></div>)
</div>
@ -940,7 +969,7 @@ directories controlled on the custom side.</div></div><hr>
the specified directory. The File_List returned should be passed to free_file_list
when it is no longer in use.</div></div><hr>
<div id='free_file_list_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.46: free_file_list</h4>
<h4>&sect;3.3.50: free_file_list</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->free_file_list(
<div style='margin-left: 4mm;'>Application_Links *app,<br>File_List list<br></div>)
</div>
@ -950,7 +979,7 @@ when it is no longer in use.</div></div><hr>
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>After this call the file list passed in should not be read or written to.</div></div><hr>
<div id='file_exists_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.47: file_exists</h4>
<h4>&sect;3.3.51: file_exists</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->file_exists(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *filename,<br>int len<br></div>)
</div>
@ -964,7 +993,7 @@ when it is no longer in use.</div></div><hr>
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero if and only if the file exists.</div></div><hr>
<div id='directory_cd_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.48: directory_cd</h4>
<h4>&sect;3.3.52: directory_cd</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->directory_cd(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *dir,<br>int *len,<br>int capacity,<br>char *rel_path,<br>int rel_len<br></div>)
</div>
@ -997,7 +1026,7 @@ 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.</div></div><hr>
<div id='get_4ed_path_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.49: get_4ed_path</h4>
<h4>&sect;3.3.53: get_4ed_path</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>bool32 app->get_4ed_path(
<div style='margin-left: 4mm;'>Application_Links *app,<br>char *out,<br>int32_t capacity<br></div>)
</div>
@ -1011,7 +1040,7 @@ folders.</div></div><hr>
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Return</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>This call returns non-zero on success.</div></div><hr>
<div id='show_mouse_cursor_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.3.50: show_mouse_cursor</h4>
<h4>&sect;3.3.54: show_mouse_cursor</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>void app->show_mouse_cursor(
<div style='margin-left: 4mm;'>Application_Links *app,<br>Mouse_Cursor_Show_Type show<br></div>)
</div>
@ -1110,10 +1139,6 @@ the range [1,16].</div></div><hr>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'>cmdid_history_forward unperforms the previous cmdid_history_backward step if possib.e</div></div>
</div>
<div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>cmdid_clean_all_lines</span></span></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'>cmdid_clean_all_lines deletes extra whitespace out the currently active buffer.</div></div>
</div>
<div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>cmdid_interactive_new</span></span></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'>cmdid_interactive_new begins an interactive dialogue to create a new buffer.</div></div>
</div>
@ -1207,11 +1232,12 @@ the range [1,16].</div></div><hr>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Buffer_Batch_Edit_Type;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>A Buffer_Batch_Edit_Type is a type of batch operation.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Values</i></b></div><div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>BatchEdit_Normal</span></span></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'></div></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'>The BatchEdit_Normal operation is always correct but does the most work.</div></div>
</div>
<div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>BatchEdit_PreserveTokens</span></span></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'></div></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'>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.</div></div>
</div>
</div><hr>
<div id='Buffer_Setting_ID_doc' style='margin-bottom: 1cm;'>
@ -1342,8 +1368,24 @@ Flags can be combined with bit or to specify a state with multiple modifiers.</d
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'></div></div>
</div>
</div><hr>
<div id='Memory_Protect_Flags_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.17: Memory_Protect_Flags</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Memory_Protect_Flags;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>TODO</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Flags</i></b></div><div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>MemProtect_Read</span> = 0x1</span></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'></div></div>
</div>
<div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>MemProtect_Write</span> = 0x2</span></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'></div></div>
</div>
<div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>MemProtect_Execute</span> = 0x4</span></div>
<div style='margin-bottom: 6mm;'><div style='margin-left: 5mm; margin-right: 5mm;'></div></div>
</div>
</div><hr>
<div id='Buffer_Create_Flag_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.17: Buffer_Create_Flag</h4>
<h4>&sect;3.4.18: Buffer_Create_Flag</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Buffer_Create_Flag;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>A Buffer_Create_Flag field specifies how a buffer should be created.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Flags</i></b></div><div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>BufferCreate_Background</span> = 0x1</span></div>
@ -1356,7 +1398,7 @@ Flags can be combined with bit or to specify a state with multiple modifiers.</d
</div>
</div><hr>
<div id='Buffer_Kill_Flag_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.18: Buffer_Kill_Flag</h4>
<h4>&sect;3.4.19: Buffer_Kill_Flag</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Buffer_Kill_Flag;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>A Buffer_Kill_Flag field specifies how a buffer should be killed.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Flags</i></b></div><div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>BufferKill_Background</span> = 0x1</span></div>
@ -1369,7 +1411,7 @@ Flags can be combined with bit or to specify a state with multiple modifiers.</d
</div>
</div><hr>
<div id='Access_Flag_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.19: Access_Flag</h4>
<h4>&sect;3.4.20: Access_Flag</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Access_Flag;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>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
@ -1399,7 +1441,7 @@ that protection flag, the object is still returned from the access call.</div><d
</div>
</div><hr>
<div id='Seek_Boundary_Flag_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.20: Seek_Boundary_Flag</h4>
<h4>&sect;3.4.21: Seek_Boundary_Flag</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Seek_Boundary_Flag;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>A Seek_Boundary_Flag field specifies a set of "boundary" types used in seeks for the
beginning or end of different types of words.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Flags</i></b></div><div>
@ -1420,7 +1462,7 @@ beginning or end of different types of words.</div><div style='margin-top: 3mm;
</div>
</div><hr>
<div id='Command_Line_Input_Flag_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.21: Command_Line_Input_Flag</h4>
<h4>&sect;3.4.22: Command_Line_Input_Flag</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Command_Line_Input_Flag;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>A Command_Line_Input_Flag field specifies the behavior of a call to a command line interface.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Flags</i></b></div><div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>CLI_OverlapWithConflict</span> = 0x1</span></div>
@ -1441,7 +1483,7 @@ beginning or end of different types of words.</div><div style='margin-top: 3mm;
</div>
</div><hr>
<div id='Auto_Indent_Flag_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.22: Auto_Indent_Flag</h4>
<h4>&sect;3.4.23: Auto_Indent_Flag</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Auto_Indent_Flag;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>An Auto_Indent_Flag field specifies the behavior of an auto indentation operation.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Flags</i></b></div><div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>AutoIndent_ClearLine</span> = 0x1</span></div>
@ -1457,7 +1499,7 @@ beginning or end of different types of words.</div><div style='margin-top: 3mm;
</div>
</div><hr>
<div id='Set_Buffer_Flag_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.23: Set_Buffer_Flag</h4>
<h4>&sect;3.4.24: Set_Buffer_Flag</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Set_Buffer_Flag;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>A Set_Buffer_Flag field specifies the behavior of an operation that sets the buffer of a view.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Flags</i></b></div><div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>SetBuffer_KeepOriginalGUI</span> = 0x1</span></div>
@ -1467,7 +1509,7 @@ beginning or end of different types of words.</div><div style='margin-top: 3mm;
</div>
</div><hr>
<div id='Input_Type_Flag_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.24: Input_Type_Flag</h4>
<h4>&sect;3.4.25: Input_Type_Flag</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>enum Input_Type_Flag;</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Description</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'>A Input_Type_Flag field specifies a set of input event types.</div><div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>Flags</i></b></div><div>
<div><span style='font-family: "Courier New", Courier, monospace; text-align: left;'><span style='font-weight: 600;'>EventOnAnyKey</span> = 0x1</span></div>
@ -1507,7 +1549,7 @@ beginning or end of different types of words.</div><div style='margin-top: 3mm;
</div>
</div><hr>
<div id='Generic_Command_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.25: Generic_Command</h4>
<h4>&sect;3.4.26: Generic_Command</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>union Generic_Command {<br>
<div style='margin-left: 8mm;'>
Command_ID cmdid;<br>
@ -1528,7 +1570,7 @@ internal command or a custom command.</div><div style='margin-top: 3mm; margin-b
</div>
</div><hr>
<div id='Key_Event_Data_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.26: Key_Event_Data</h4>
<h4>&sect;3.4.27: Key_Event_Data</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Key_Event_Data {<br>
<div style='margin-left: 8mm;'>
Key_Code keycode;<br>
@ -1562,7 +1604,7 @@ at the time of the event.</div><div style='margin-top: 3mm; margin-bottom: 3mm;
</div>
</div><hr>
<div id='Mouse_State_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.27: Mouse_State</h4>
<h4>&sect;3.4.28: Mouse_State</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Mouse_State {<br>
<div style='margin-left: 8mm;'>
char l;<br>
@ -1622,7 +1664,7 @@ mouse if in the window.</div><div style='margin-top: 3mm; margin-bottom: 3mm; co
</div>
</div><hr>
<div id='Range_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.28: Range</h4>
<h4>&sect;3.4.29: Range</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>union Range {<br>
<div style='margin-left: 8mm;'>
struct {<br>
@ -1662,7 +1704,7 @@ Throughout the API ranges are thought of in the form [min,max</div><div style='m
</div>
</div><hr>
<div id='File_Info_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.29: File_Info</h4>
<h4>&sect;3.4.30: File_Info</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct File_Info {<br>
<div style='margin-left: 8mm;'>
char * filename;<br>
@ -1685,7 +1727,7 @@ int folder;<br>
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#File_List_doc'>File_List</a></div></div><hr>
<div id='File_List_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.30: File_List</h4>
<h4>&sect;3.4.31: File_List</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct File_List {<br>
<div style='margin-left: 8mm;'>
void * block;<br>
@ -1713,7 +1755,7 @@ int block_size;<br>
</div>
</div><hr>
<div id='Buffer_Identifier_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.31: Buffer_Identifier</h4>
<h4>&sect;3.4.32: Buffer_Identifier</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Buffer_Identifier {<br>
<div style='margin-left: 8mm;'>
char * name;<br>
@ -1738,7 +1780,7 @@ can either be a name or an id. If the</div><div style='margin-top: 3mm; margin-
</div>
</div><hr>
<div id='GUI_Scroll_Vars_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.32: GUI_Scroll_Vars</h4>
<h4>&sect;3.4.33: GUI_Scroll_Vars</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct GUI_Scroll_Vars {<br>
<div style='margin-left: 8mm;'>
float scroll_y;<br>
@ -1776,7 +1818,7 @@ int32_t prev_target_x;<br>
</div>
</div><hr>
<div id='Full_Cursor_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.33: Full_Cursor</h4>
<h4>&sect;3.4.34: Full_Cursor</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Full_Cursor {<br>
<div style='margin-left: 8mm;'>
int32_t pos;<br>
@ -1820,7 +1862,7 @@ coordinate system supported by 4coder.</div><div style='margin-top: 3mm; margin-
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#4coder_Buffer_Positioning_System_doc'>4coder_Buffer_Positioning_System</a></div></div><hr>
<div id='Buffer_Seek_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.34: Buffer_Seek</h4>
<h4>&sect;3.4.35: Buffer_Seek</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Buffer_Seek {<br>
<div style='margin-left: 8mm;'>
Buffer_Seek_Type type;<br>
@ -1885,7 +1927,7 @@ for concisely creating Buffer_Seek structs. They can be found in 4coder_buffer_
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Buffer_Seek_Type_doc'>Buffer_Seek_Type</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#4coder_Buffer_Positioning_System_doc'>4coder_Buffer_Positioning_System</a></div></div><hr>
<div id='Buffer_Edit_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.35: Buffer_Edit</h4>
<h4>&sect;3.4.36: Buffer_Edit</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Buffer_Edit {<br>
<div style='margin-left: 8mm;'>
int32_t str_start;<br>
@ -1915,7 +1957,7 @@ will be replaced into the buffer.</div><div style='margin-top: 3mm; margin-botto
</div>
</div><hr>
<div id='Buffer_Summary_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.36: Buffer_Summary</h4>
<h4>&sect;3.4.37: Buffer_Summary</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Buffer_Summary {<br>
<div style='margin-left: 8mm;'>
bool32 exists;<br>
@ -1990,7 +2032,7 @@ bool32 unwrapped_lines;<br>
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div></div><hr>
<div id='View_Summary_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.37: View_Summary</h4>
<h4>&sect;3.4.38: View_Summary</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct View_Summary {<br>
<div style='margin-left: 8mm;'>
bool32 exists;<br>
@ -2060,7 +2102,7 @@ GUI_Scroll_Vars scroll_vars;<br>
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Access_Flag_doc'>Access_Flag</a></div></div><hr>
<div id='User_Input_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.38: User_Input</h4>
<h4>&sect;3.4.39: User_Input</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct User_Input {<br>
<div style='margin-left: 8mm;'>
User_Input_Type_ID type;<br>
@ -2097,7 +2139,7 @@ Generic_Command command;<br>
</div>
<div style='margin-top: 3mm; margin-bottom: 3mm; color: #309030;'><b><i>See Also</i></b></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#User_Input_Type_ID_doc'>User_Input_Type_ID</a></div><div style='margin-left: 5mm; margin-right: 5mm;'><a href='#Generic_Command_doc'>Generic_Command</a></div></div><hr>
<div id='Query_Bar_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.39: Query_Bar</h4>
<h4>&sect;3.4.40: Query_Bar</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Query_Bar {<br>
<div style='margin-left: 8mm;'>
String prompt;<br>
@ -2116,7 +2158,7 @@ that will be displayed as a drop down bar durring an interactive command.</div><
</div>
</div><hr>
<div id='Event_Message_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.40: Event_Message</h4>
<h4>&sect;3.4.41: Event_Message</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Event_Message {<br>
<div style='margin-left: 8mm;'>
int type;<br>
@ -2129,7 +2171,7 @@ int type;<br>
</div>
</div><hr>
<div id='Theme_Color_doc' style='margin-bottom: 1cm;'>
<h4>&sect;3.4.41: Theme_Color</h4>
<h4>&sect;3.4.42: Theme_Color</h4>
<div style='font-family: "Courier New", Courier, monospace; text-align: left; margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; background: #DFDFDF; padding: 0.25em;'>struct Theme_Color {<br>
<div style='margin-left: 8mm;'>
Style_Tag tag;<br>

View File

@ -1,8 +1,12 @@
#define EXEC_COMMAND_SIG(n) bool32 n(Application_Links *app, Command_ID command_id)
#define EXEC_SYSTEM_COMMAND_SIG(n) bool32 n(Application_Links *app, View_Summary *view, Buffer_Identifier buffer, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Input_Flag flags)
#define MEMORY_ALLOC_SIG(n) void* n(Application_Links *app, int32_t size)
#define MEMORY_SET_PROTECTION_SIG(n) int32_t n(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags)
#define MEMORY_FREE_SIG(n) void n(Application_Links *app, void *mem)
#define CLIPBOARD_POST_SIG(n) void n(Application_Links *app, int32_t clipboard_id, char *str, int32_t len)
#define CLIPBOARD_COUNT_SIG(n) int32_t n(Application_Links *app, int32_t clipboard_id)
#define CLIPBOARD_INDEX_SIG(n) int32_t n(Application_Links *app, int32_t clipboard_id, int32_t item_index, char *out, int32_t len)
#define GET_BUFFER_COUNT_SIG(n) int32_t n(Application_Links *app)
#define GET_BUFFER_FIRST_SIG(n) Buffer_Summary n(Application_Links *app, Access_Flag access)
#define GET_BUFFER_NEXT_SIG(n) void n(Application_Links *app, Buffer_Summary *buffer, Access_Flag access)
#define GET_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, Buffer_ID buffer_id, Access_Flag access)
@ -51,9 +55,13 @@
extern "C"{
typedef EXEC_COMMAND_SIG(Exec_Command_Function);
typedef EXEC_SYSTEM_COMMAND_SIG(Exec_System_Command_Function);
typedef MEMORY_ALLOC_SIG(Memory_Alloc_Function);
typedef MEMORY_SET_PROTECTION_SIG(Memory_Set_Protection_Function);
typedef MEMORY_FREE_SIG(Memory_Free_Function);
typedef CLIPBOARD_POST_SIG(Clipboard_Post_Function);
typedef CLIPBOARD_COUNT_SIG(Clipboard_Count_Function);
typedef CLIPBOARD_INDEX_SIG(Clipboard_Index_Function);
typedef GET_BUFFER_COUNT_SIG(Get_Buffer_Count_Function);
typedef GET_BUFFER_FIRST_SIG(Get_Buffer_First_Function);
typedef GET_BUFFER_NEXT_SIG(Get_Buffer_Next_Function);
typedef GET_BUFFER_SIG(Get_Buffer_Function);
@ -105,9 +113,13 @@ struct Application_Links{
int memory_size;
Exec_Command_Function *exec_command;
Exec_System_Command_Function *exec_system_command;
Memory_Alloc_Function *memory_alloc;
Memory_Set_Protection_Function *memory_set_protection;
Memory_Free_Function *memory_free;
Clipboard_Post_Function *clipboard_post;
Clipboard_Count_Function *clipboard_count;
Clipboard_Index_Function *clipboard_index;
Get_Buffer_Count_Function *get_buffer_count;
Get_Buffer_First_Function *get_buffer_first;
Get_Buffer_Next_Function *get_buffer_next;
Get_Buffer_Function *get_buffer;
@ -161,9 +173,13 @@ struct Application_Links{
#define FillAppLinksAPI(app_links) do{\
app_links->exec_command = Exec_Command;\
app_links->exec_system_command = Exec_System_Command;\
app_links->memory_alloc = Memory_Alloc;\
app_links->memory_set_protection = Memory_Set_Protection;\
app_links->memory_free = Memory_Free;\
app_links->clipboard_post = Clipboard_Post;\
app_links->clipboard_count = Clipboard_Count;\
app_links->clipboard_index = Clipboard_Index;\
app_links->get_buffer_count = Get_Buffer_Count;\
app_links->get_buffer_first = Get_Buffer_First;\
app_links->get_buffer_next = Get_Buffer_Next;\
app_links->get_buffer = Get_Buffer;\

View File

@ -11,6 +11,414 @@
#include <assert.h>
//
// Memory
//
static Partition scratch;
//
// Buffer Streaming
//
struct Stream_Chunk{
Application_Links *app;
Buffer_Summary *buffer;
char *base_data;
int start, end;
int min_start, max_end;
int data_size;
char *data;
};
int
round_down(int x, int b){
int r = 0;
if (x >= 0){
r = x - (x % b);
}
return(r);
}
int
round_up(int x, int b){
int r = 0;
if (x >= 0){
r = x - (x % b) + b;
}
return(r);
}
void
refresh_buffer(Application_Links *app, Buffer_Summary *buffer){
*buffer = app->get_buffer(app, buffer->buffer_id, AccessAll);
}
void
refresh_view(Application_Links *app, View_Summary *view){
*view = app->get_view(app, view->view_id, AccessAll);
}
int
init_stream_chunk(Stream_Chunk *chunk,
Application_Links *app, Buffer_Summary *buffer,
int pos, char *data, int size){
int result = false;
refresh_buffer(app, buffer);
if (pos >= 0 && pos < buffer->size && size > 0){
chunk->app = app;
chunk->buffer = buffer;
chunk->base_data = data;
chunk->data_size = size;
chunk->start = round_down(pos, size);
chunk->end = round_up(pos, size);
if (chunk->max_end > buffer->size
|| chunk->max_end == 0){
chunk->max_end = buffer->size;
}
if (chunk->max_end && chunk->max_end < chunk->end){
chunk->end = chunk->max_end;
}
if (chunk->min_start && chunk->min_start > chunk->start){
chunk->start = chunk->min_start;
}
if (chunk->start < chunk->end){
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
result = true;
}
}
return(result);
}
int
forward_stream_chunk(Stream_Chunk *chunk){
Application_Links *app = chunk->app;
Buffer_Summary *buffer = chunk->buffer;
int result = false;
refresh_buffer(app, buffer);
if (chunk->end < buffer->size){
chunk->start = chunk->end;
chunk->end += chunk->data_size;
if (chunk->max_end && chunk->max_end < chunk->end){
chunk->end = chunk->max_end;
}
if (chunk->min_start && chunk->min_start > chunk->start){
chunk->start = chunk->min_start;
}
if (chunk->start < chunk->end){
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
result = true;
}
}
return(result);
}
int
backward_stream_chunk(Stream_Chunk *chunk){
Application_Links *app = chunk->app;
Buffer_Summary *buffer = chunk->buffer;
int result = false;
refresh_buffer(app, buffer);
if (chunk->start > 0){
chunk->end = chunk->start;
chunk->start -= chunk->data_size;
if (chunk->max_end && chunk->max_end < chunk->end){
chunk->end = chunk->max_end;
}
if (chunk->min_start && chunk->min_start > chunk->start){
chunk->start = chunk->min_start;
}
if (chunk->start < chunk->end){
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
result = true;
}
}
return(result);
}
void
buffer_seek_delimiter_forward(Application_Links *app, Buffer_Summary *buffer,
int pos, char delim, int *result){
if (buffer->exists){
char chunk[1024];
int size = sizeof(chunk);
Stream_Chunk stream = {0};
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
int still_looping = 1;
do{
for(; pos < stream.end; ++pos){
char at_pos = stream.data[pos];
if (at_pos == delim){
*result = pos;
goto finished;
}
}
still_looping = forward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = buffer->size;
finished:;
}
void
buffer_seek_delimiter_backward(Application_Links *app, Buffer_Summary *buffer,
int pos, char delim, int *result){
if (buffer->exists){
char chunk[1024];
int size = sizeof(chunk);
Stream_Chunk stream = {0};
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
int still_looping = 1;
do{
for(; pos >= stream.start; --pos){
char at_pos = stream.data[pos];
if (at_pos == delim){
*result = pos;
goto finished;
}
}
still_looping = backward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = 0;
finished:;
}
// TODO(allen): This duplication is driving me crazy... I've gotta
// upgrade the meta programming system another level.
// NOTE(allen): This is limitted to a string size of 512.
// You can push it up or do something more clever by just
// replacing char read_buffer[512]; with more memory.
void
buffer_seek_string_forward(Application_Links *app, Buffer_Summary *buffer,
int pos, int end, char *str, int size, int *result){
char read_buffer[512];
if (size <= 0){
*result = pos;
}
else if (size > sizeof(read_buffer)){
*result = pos;
}
else{
if (buffer->exists){
String read_str = make_fixed_width_string(read_buffer);
String needle_str = make_string(str, size);
char first_char = str[0];
read_str.size = size;
char chunk[1024];
int chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
stream.max_end = end;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
int still_looping = 1;
do{
for(; pos < stream.end; ++pos){
char at_pos = stream.data[pos];
if (at_pos == first_char){
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
if (match(needle_str, read_str)){
*result = pos;
goto finished;
}
}
}
still_looping = forward_stream_chunk(&stream);
}while (still_looping);
}
}
if (end == 0){
*result = buffer->size;
}
else{
*result = end;
}
finished:;
}
}
// NOTE(allen): This is limitted to a string size of 512.
// You can push it up or do something more clever by just
// replacing char read_buffer[512]; with more memory.
void
buffer_seek_string_backward(Application_Links *app, Buffer_Summary *buffer,
int pos, int min, char *str, int size, int *result){
char read_buffer[512];
if (size <= 0){
*result = min-1;
}
else if (size > sizeof(read_buffer)){
*result = min-1;
}
else{
if (buffer->exists){
String read_str = make_fixed_width_string(read_buffer);
String needle_str = make_string(str, size);
char first_char = str[0];
read_str.size = size;
char chunk[1024];
int chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
stream.min_start = min;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
int still_looping = 1;
do{
for(; pos >= stream.start; --pos){
char at_pos = stream.data[pos];
if (at_pos == first_char){
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
if (match(needle_str, read_str)){
*result = pos;
goto finished;
}
}
}
still_looping = backward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = min-1;
finished:;
}
}
// NOTE(allen): This is limitted to a string size of 512.
// You can push it up or do something more clever by just
// replacing char read_buffer[512]; with more memory.
void
buffer_seek_string_insensitive_forward(Application_Links *app, Buffer_Summary *buffer,
int pos, char *str, int size, int *result){
char read_buffer[512];
char chunk[1024];
int chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
if (size <= 0){
*result = buffer->size;
}
else if (size > sizeof(read_buffer)){
*result = buffer->size;
}
else{
if (buffer->exists){
String read_str = make_fixed_width_string(read_buffer);
String needle_str = make_string(str, size);
char first_char = char_to_upper(str[0]);
read_str.size = size;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
int still_looping = 1;
do{
for(; pos < stream.end; ++pos){
char at_pos = char_to_upper(stream.data[pos]);
if (at_pos == first_char){
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
if (match_insensitive(needle_str, read_str)){
*result = pos;
goto finished;
}
}
}
still_looping = forward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = buffer->size;
finished:;
}
}
// NOTE(allen): This is limitted to a string size of 512.
// You can push it up or do something more clever by just
// replacing char read_buffer[512]; with more memory.
void
buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_Summary *buffer,
int pos, char *str, int size, int *result){
char read_buffer[512];
char chunk[1024];
int chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
if (size <= 0){
*result = -1;
}
else if (size > sizeof(read_buffer)){
*result = -1;
}
else{
if (buffer->exists){
String read_str = make_fixed_width_string(read_buffer);
String needle_str = make_string(str, size);
char first_char = char_to_upper(str[0]);
read_str.size = size;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
int still_looping = 1;
do{
for(; pos >= stream.start; --pos){
char at_pos = char_to_upper(stream.data[pos]);
if (at_pos == first_char){
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
if (match_insensitive(needle_str, read_str)){
*result = pos;
goto finished;
}
}
}
still_looping = backward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = -1;
finished:;
}
}
//
// Fundamental Editing
//
inline float
get_view_y(View_Summary view){
float y = view.cursor.wrapped_y;
@ -29,10 +437,6 @@ get_view_x(View_Summary view){
return(x);
}
//
// Fundamental Editing
//
CUSTOM_COMMAND_SIG(write_character){
unsigned int access = AccessOpen;
View_Summary view = app->get_active_view(app, access);
@ -304,6 +708,12 @@ CUSTOM_COMMAND_SIG(cut){
clipboard_cut(app, range.min, range.max, 0, access);
}
enum Rewrite_Type{
RewriteNone,
RewritePaste,
RewriteWordComplete
};
struct View_Paste_Index{
int rewrite;
int next_rewrite;
@ -319,7 +729,7 @@ CUSTOM_COMMAND_SIG(paste){
if (count > 0){
View_Summary view = app->get_active_view(app, access);
view_paste_index[view.view_id].next_rewrite = true;
view_paste_index[view.view_id].next_rewrite = RewritePaste;
int paste_index = 0;
view_paste_index[view.view_id].index = paste_index;
@ -355,11 +765,8 @@ CUSTOM_COMMAND_SIG(paste_next){
if (count > 0){
View_Summary view = app->get_active_view(app, access);
// NOTE(allen): THIS is a very temporary poop-sauce
// system that I just threw in to get this working.
// Please don't start calling it anywhere.
if (view_paste_index[view.view_id].rewrite){
view_paste_index[view.view_id].next_rewrite = true;
if (view_paste_index[view.view_id].rewrite == RewritePaste){
view_paste_index[view.view_id].next_rewrite = RewritePaste;
int paste_index = view_paste_index[view.view_id].index + 1;
view_paste_index[view.view_id].index = paste_index;
@ -823,8 +1230,9 @@ CUSTOM_COMMAND_SIG(if0_off){
move_past_lead_whitespace(app, &view, &buffer);
}
//
//
// Fast Deletes
//
CUSTOM_COMMAND_SIG(backspace_word){
@ -1009,6 +1417,28 @@ CUSTOM_COMMAND_SIG(open_file_in_quotes_regular){
# define open_file_in_quotes open_file_in_quotes_regular
#endif
CUSTOM_COMMAND_SIG(open_in_other_regular){
exec_command(app, change_active_panel_regular);
exec_command(app, cmdid_interactive_open);
}
// TODO(allen): This is a bit nasty. I want a system for picking
// the most advanced and correct version of a command to bind to a
// name based on which files are included.
#ifndef OPEN_IN_OTHER
# define OPEN_IN_OTHER 1
#elif OPEN_IN_OTHER <= 1
# undef OPEN_IN_OTHER
# define OPEN_IN_OTHER 1
#endif
#if OPEN_IN_OTHER <= 1
# ifdef open_in_other
# undef open_in_other
# endif
# define open_in_other open_in_other_regular
#endif
CUSTOM_COMMAND_SIG(save_as){
@ -1018,15 +1448,14 @@ CUSTOM_COMMAND_SIG(save_as){
CUSTOM_COMMAND_SIG(goto_line){
unsigned int access = AccessProtected;
int line_number;
Query_Bar bar;
Query_Bar bar = {0};
char string_space[256];
bar.prompt = make_lit_string("Goto Line: ");
bar.string = make_fixed_width_string(string_space);
if (query_user_number(app, &bar)){
line_number = str_to_int(bar.string);
int line_number = str_to_int(bar.string);
active_view_to_line(app, access, line_number);
}
}
@ -1070,6 +1499,7 @@ isearch(Application_Links *app, int start_reversed){
// NOTE(allen): If we're getting mouse events here it's a 4coder bug, because we
// only asked to intercept key events.
assert(in.type == UserInputKey);
int made_change = 0;
@ -1095,7 +1525,7 @@ isearch(Application_Links *app, int start_reversed){
if ((in.command.command == reverse_search) ||
in.key.keycode == key_page_up || in.key.keycode == key_up) step_backward = 1;
int start_pos = pos;
start_pos = pos;
if (step_forward && reverse){
start_pos = match.start + 1;
pos = start_pos;
@ -1158,11 +1588,11 @@ isearch(Application_Links *app, int start_reversed){
}
CUSTOM_COMMAND_SIG(search){
isearch(app, 0);
isearch(app, false);
}
CUSTOM_COMMAND_SIG(reverse_search){
isearch(app, 1);
isearch(app, true);
}
CUSTOM_COMMAND_SIG(replace_in_range){
@ -1193,14 +1623,15 @@ CUSTOM_COMMAND_SIG(replace_in_range){
int pos, new_pos;
pos = range.min;
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
buffer_seek_string_forward(app, &buffer, pos, 0, r.str, r.size, &new_pos);
while (new_pos + r.size <= range.end){
app->buffer_replace_range(app, &buffer, new_pos, new_pos + r.size, w.str, w.size);
refresh_view(app, &view);
range = get_range(&view);
pos = new_pos + w.size;
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
buffer_seek_string_forward(app, &buffer, pos, 0, r.str, r.size, &new_pos);
}
}
@ -1239,7 +1670,7 @@ CUSTOM_COMMAND_SIG(query_replace){
buffer = app->get_buffer(app, view.buffer_id, access);
pos = view.cursor.pos;
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
buffer_seek_string_forward(app, &buffer, pos, 0, r.str, r.size, &new_pos);
User_Input in = {0};
while (new_pos < buffer.size){
@ -1260,7 +1691,7 @@ CUSTOM_COMMAND_SIG(query_replace){
pos = match.max;
}
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
buffer_seek_string_forward(app, &buffer, pos, 0, r.str, r.size, &new_pos);
}
app->view_set_highlight(app, &view, 0, 0, 0);
@ -1269,6 +1700,10 @@ CUSTOM_COMMAND_SIG(query_replace){
app->view_set_cursor(app, &view, seek_pos(pos), 1);
}
//
// Fast Buffer Management
//
CUSTOM_COMMAND_SIG(close_all_code){
String extension;
Buffer_Summary buffer;
@ -1340,8 +1775,8 @@ char command_space[1024];
char hot_directory_space[1024];
CUSTOM_COMMAND_SIG(execute_any_cli){
Query_Bar bar_out, bar_cmd;
String hot_directory;
Query_Bar bar_out = {0};
Query_Bar bar_cmd = {0};
bar_out.prompt = make_lit_string("Output Buffer: ");
bar_out.string = make_fixed_width_string(out_buffer_space);
@ -1351,7 +1786,7 @@ CUSTOM_COMMAND_SIG(execute_any_cli){
bar_cmd.string = make_fixed_width_string(command_space);
if (!query_user_string(app, &bar_cmd)) return;
hot_directory = make_fixed_width_string(hot_directory_space);
String hot_directory = make_fixed_width_string(hot_directory_space);
hot_directory.size = app->directory_get_hot(app, hot_directory.str, hot_directory.memory_size);
unsigned int access = AccessAll;
@ -1365,11 +1800,9 @@ CUSTOM_COMMAND_SIG(execute_any_cli){
}
CUSTOM_COMMAND_SIG(execute_previous_cli){
String out_buffer, cmd, hot_directory;
out_buffer = make_string_slowly(out_buffer_space);
cmd = make_string_slowly(command_space);
hot_directory = make_string_slowly(hot_directory_space);
String out_buffer = make_string_slowly(out_buffer_space);
String cmd = make_string_slowly(command_space);
String hot_directory = make_string_slowly(hot_directory_space);
if (out_buffer.size > 0 && cmd.size > 0 && hot_directory.size > 0){
unsigned int access = AccessAll;
@ -1383,28 +1816,6 @@ CUSTOM_COMMAND_SIG(execute_previous_cli){
}
}
CUSTOM_COMMAND_SIG(open_in_other_regular){
exec_command(app, change_active_panel_regular);
exec_command(app, cmdid_interactive_open);
}
// TODO(allen): This is a bit nasty. I want a system for picking
// the most advanced and correct version of a command to bind to a
// name based on which files are included.
#ifndef OPEN_IN_OTHER
# define OPEN_IN_OTHER 1
#elif OPEN_IN_OTHER <= 1
# undef OPEN_IN_OTHER
# define OPEN_IN_OTHER 1
#endif
#if OPEN_IN_OTHER <= 1
# ifdef open_in_other
# undef open_in_other
# endif
# define open_in_other open_in_other_regular
#endif
//
// Auto Indenting and Whitespace
//
@ -1515,8 +1926,8 @@ CUSTOM_COMMAND_SIG(clean_all_lines){
// NOTE(allen|a4.0.9): This is provided to establish a default method of getting
// a "build directory". This function tries to setup the build directory in the
// directory of the given buffer, it cannot it get's the 4coder hot directory.
// This behavior is a little different than previous versions of 4coder.
// directory of the given buffer, if it cannot get that information it get's the
// 4coder hot directory.
//
// There is no requirement that a custom build system in 4coder actually use the
// directory given by this function.
@ -1674,8 +2085,8 @@ execute_standard_build(Application_Links *app, View_Summary *view,
char dir_space[512];
String dir = make_fixed_width_string(dir_space);
char command_space[512];
String command = make_fixed_width_string(command_space);
char command_str_space[512];
String command = make_fixed_width_string(command_str_space);
int build_dir_type = get_build_directory(app, active_buffer, &dir);
@ -1750,6 +2161,193 @@ CUSTOM_COMMAND_SIG(eol_nixify){
app->buffer_set_setting(app, &buffer, BufferSetting_Eol, false);
}
//
// "Full Search" Based Commands
//
#include "4coder_table.cpp"
#include "4coder_search.cpp"
struct Word_Complete_State{
Search_Set set;
Search_Iter iter;
Table hits;
String_Space str;
int word_start;
int word_end;
int initialized;
};
static Word_Complete_State complete_state = {0};
CUSTOM_COMMAND_SIG(word_complete){
View_Summary view = app->get_active_view(app, AccessOpen);
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, AccessOpen);
// NOTE(allen): I just do this because this command is a lot of work
// and there is no point in doing any of it if nothing will happen anyway.
if (buffer.exists){
int do_init = false;
if (view_paste_index[view.view_id].rewrite != RewriteWordComplete){
do_init = true;
}
view_paste_index[view.view_id].next_rewrite != RewriteWordComplete;
if (!complete_state.initialized){
do_init = true;
}
int word_end = 0;
int word_start = 0;
int cursor_pos = 0;
int size = 0;
if (do_init){
// NOTE(allen): Get the range where the
// partial word is written.
word_end = view.cursor.pos;
word_start = word_end;
cursor_pos = word_end - 1;
char space[1024];
Stream_Chunk chunk = {0};
if (init_stream_chunk(&chunk, app, &buffer,
cursor_pos, space, sizeof(space))){
int still_looping = true;
do{
for (; cursor_pos >= chunk.start; --cursor_pos){
char c = chunk.data[cursor_pos];
if (char_is_alpha(c)){
word_start = cursor_pos;
}
else if (!char_is_numeric(c)){
goto double_break;
}
}
still_looping = backward_stream_chunk(&chunk);
}while(still_looping);
}
double_break:;
size = word_end - word_start;
if (size == 0){
complete_state.initialized = false;
return;
}
// NOTE(allen): Initialize the search iterator
// with the partial word.
complete_state.initialized = true;
search_iter_init(app, &complete_state.iter, size);
app->buffer_read_range(app, &buffer, word_start, word_end,
complete_state.iter.word.str);
complete_state.iter.word.size = size;
// NOTE(allen): Initialize the set of ranges
// to be searched.
int buffer_count = app->get_buffer_count(app);
search_set_init(app, &complete_state.set, buffer_count);
Search_Range *ranges = complete_state.set.ranges;
ranges[0].type = SearchRange_Wave;
ranges[0].buffer = buffer.buffer_id;
ranges[0].start = 0;
ranges[0].size = buffer.size;
ranges[0].mid_start = word_start;
ranges[0].mid_size = size;
int j = 1;
for (Buffer_Summary buffer_it = app->get_buffer_first(app, AccessAll);
buffer_it.exists;
app->get_buffer_next(app, &buffer_it, AccessAll)){
if (buffer.buffer_id != buffer_it.buffer_id){
ranges[j].type = SearchRange_FrontToBack;
ranges[j].buffer = buffer_it.buffer_id;
ranges[j].start = 0;
ranges[j].size = buffer_it.size;
++j;
}
}
complete_state.set.count = j;
// NOTE(allen): Initialize the search hit table.
search_hits_init(app, &complete_state.hits, &complete_state.str,
100, (4 << 10));
search_hit_add(app, &complete_state.hits, &complete_state.str,
complete_state.iter.word.str,
complete_state.iter.word.size);
complete_state.word_start = word_start;
complete_state.word_end = word_end;
}
else{
word_start = complete_state.word_start;
word_end = complete_state.word_end;
size = complete_state.iter.word.size;
}
// NOTE(allen): Iterate through matches.
if (size > 0){
for (;;){
int match_size = 0;
Search_Match match =
search_next_match(app, &complete_state.set,
&complete_state.iter);
if (match.found_match){
int match_size = match.end - match.start;
char *spare = (char*)GET_MEMORY(match_size);
app->buffer_read_range(app, &match.buffer,
match.start, match.end, spare);
if (search_hit_add(app, &complete_state.hits, &complete_state.str,
spare, match_size)){
app->buffer_replace_range(app, &buffer, word_start, word_end,
spare, match_size);
app->view_set_cursor(app, &view,
seek_pos(word_start + match_size),
true);
complete_state.word_end = word_start + match_size;
complete_state.set.ranges[0].mid_size = match_size;
FREE_MEMORY(spare);
break;
}
FREE_MEMORY(spare);
}
else{
complete_state.iter.pos = 0;
complete_state.iter.i = 0;
search_hits_init(app, &complete_state.hits, &complete_state.str,
100, (4 << 10));
search_hit_add(app, &complete_state.hits, &complete_state.str,
complete_state.iter.word.str,
complete_state.iter.word.size);
match_size = complete_state.iter.word.size;
char *str = complete_state.iter.word.str;
app->buffer_replace_range(app, &buffer, word_start, word_end,
str, match_size);
app->view_set_cursor(app, &view,
seek_pos(word_start + match_size),
true);
complete_state.word_end = word_start + match_size;
complete_state.set.ranges[0].mid_size = match_size;
break;
}
}
}
}
}
//
//
//
CUSTOM_COMMAND_SIG(execute_arbitrary_command){
// NOTE(allen): This isn't a super powerful version of this command, I will expand
// upon it so that it has all the cmdid_* commands by default. However, with this

View File

@ -417,365 +417,13 @@ get_active_buffer(Application_Links *app, unsigned int access){
return(buffer);
}
struct Stream_Chunk{
Application_Links *app;
Buffer_Summary *buffer;
char *base_data;
int start, end;
int data_size;
char *data;
};
int
round_down(int x, int b){
int r = 0;
if (x >= 0){
r = x - (x % b);
}
return(r);
}
int
round_up(int x, int b){
int r = 0;
if (x >= 0){
r = x - (x % b) + b;
}
return(r);
}
void
refresh_buffer(Application_Links *app, Buffer_Summary *buffer){
*buffer = app->get_buffer(app, buffer->buffer_id, AccessAll);
}
void
refresh_view(Application_Links *app, View_Summary *view){
*view = app->get_view(app, view->view_id, AccessAll);
}
int
init_stream_chunk(Stream_Chunk *chunk,
Application_Links *app, Buffer_Summary *buffer,
int pos, char *data, int size){
int result = 0;
refresh_buffer(app, buffer);
if (pos >= 0 && pos < buffer->size && size > 0){
result = 1;
chunk->app = app;
chunk->buffer = buffer;
chunk->base_data = data;
chunk->data_size = size;
chunk->start = round_down(pos, size);
chunk->end = round_up(pos, size);
if (chunk->end > buffer->size){
chunk->end = buffer->size;
}
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
}
inline char
buffer_get_char(Application_Links *app, Buffer_Summary *buffer, int pos){
char result = 0;
app->buffer_read_range(app, buffer, pos, pos+1, &result);
return(result);
}
int
forward_stream_chunk(Stream_Chunk *chunk){
Application_Links *app = chunk->app;
Buffer_Summary *buffer = chunk->buffer;
int result = 0;
refresh_buffer(app, buffer);
if (chunk->end < buffer->size){
result = 1;
chunk->start = chunk->end;
chunk->end += chunk->data_size;
if (chunk->end > buffer->size){
chunk->end = buffer->size;
}
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
}
return(result);
}
int
backward_stream_chunk(Stream_Chunk *chunk){
Application_Links *app = chunk->app;
Buffer_Summary *buffer = chunk->buffer;
int result = 0;
refresh_buffer(app, buffer);
if (chunk->start > 0){
result = 1;
chunk->end = chunk->start;
chunk->start -= chunk->data_size;
if (chunk->start < 0){
chunk->start = 0;
}
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
}
return(result);
}
void
buffer_seek_delimiter_forward(Application_Links *app, Buffer_Summary *buffer,
int pos, char delim, int *result){
if (buffer->exists){
char chunk[1024];
int size = sizeof(chunk);
Stream_Chunk stream = {0};
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
int still_looping = 1;
do{
for(; pos < stream.end; ++pos){
char at_pos = stream.data[pos];
if (at_pos == delim){
*result = pos;
goto finished;
}
}
still_looping = forward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = buffer->size;
finished:;
}
void
buffer_seek_delimiter_backward(Application_Links *app, Buffer_Summary *buffer,
int pos, char delim, int *result){
if (buffer->exists){
char chunk[1024];
int size = sizeof(chunk);
Stream_Chunk stream = {0};
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
int still_looping = 1;
do{
for(; pos >= stream.start; --pos){
char at_pos = stream.data[pos];
if (at_pos == delim){
*result = pos;
goto finished;
}
}
still_looping = backward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = 0;
finished:;
}
// TODO(allen): This duplication is driving me crazy... I've gotta
// upgrade the meta programming system another level.
// NOTE(allen): This is limitted to a string size of 512.
// You can push it up or do something more clever by just
// replacing char read_buffer[512]; with more memory.
void
buffer_seek_string_forward(Application_Links *app, Buffer_Summary *buffer,
int pos, char *str, int size, int *result){
char read_buffer[512];
char chunk[1024];
int chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
if (size <= 0){
*result = pos;
}
else if (size > sizeof(read_buffer)){
*result = pos;
}
else{
if (buffer->exists){
String read_str = make_fixed_width_string(read_buffer);
String needle_str = make_string(str, size);
char first_char = str[0];
read_str.size = size;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
int still_looping = 1;
do{
for(; pos < stream.end; ++pos){
char at_pos = stream.data[pos];
if (at_pos == first_char){
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
if (match(needle_str, read_str)){
*result = pos;
goto finished;
}
}
}
still_looping = forward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = buffer->size;
finished:;
}
}
// NOTE(allen): This is limitted to a string size of 512.
// You can push it up or do something more clever by just
// replacing char read_buffer[512]; with more memory.
void
buffer_seek_string_backward(Application_Links *app, Buffer_Summary *buffer,
int pos, char *str, int size, int *result){
char read_buffer[512];
char chunk[1024];
int chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
if (size <= 0){
*result = 0;
}
else if (size > sizeof(read_buffer)){
*result = 0;
}
else{
if (buffer->exists){
String read_str = make_fixed_width_string(read_buffer);
String needle_str = make_string(str, size);
char first_char = str[0];
read_str.size = size;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
int still_looping = 1;
do{
for(; pos >= stream.start; --pos){
char at_pos = stream.data[pos];
if (at_pos == first_char){
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
if (match(needle_str, read_str)){
*result = pos;
goto finished;
}
}
}
still_looping = backward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = 0;
finished:;
}
}
// NOTE(allen): This is limitted to a string size of 512.
// You can push it up or do something more clever by just
// replacing char read_buffer[512]; with more memory.
void
buffer_seek_string_insensitive_forward(Application_Links *app, Buffer_Summary *buffer,
int pos, char *str, int size, int *result){
char read_buffer[512];
char chunk[1024];
int chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
if (size <= 0){
*result = pos;
}
else if (size > sizeof(read_buffer)){
*result = pos;
}
else{
if (buffer->exists){
String read_str = make_fixed_width_string(read_buffer);
String needle_str = make_string(str, size);
char first_char = char_to_upper(str[0]);
read_str.size = size;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
int still_looping = 1;
do{
for(; pos < stream.end; ++pos){
char at_pos = char_to_upper(stream.data[pos]);
if (at_pos == first_char){
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
if (match_insensitive(needle_str, read_str)){
*result = pos;
goto finished;
}
}
}
still_looping = forward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = buffer->size;
finished:;
}
}
// NOTE(allen): This is limitted to a string size of 512.
// You can push it up or do something more clever by just
// replacing char read_buffer[512]; with more memory.
void
buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_Summary *buffer,
int pos, char *str, int size, int *result){
char read_buffer[512];
char chunk[1024];
int chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
if (size <= 0){
*result = -1;
}
else if (size > sizeof(read_buffer)){
*result = -1;
}
else{
if (buffer->exists){
String read_str = make_fixed_width_string(read_buffer);
String needle_str = make_string(str, size);
char first_char = char_to_upper(str[0]);
read_str.size = size;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
int still_looping = 1;
do{
for(; pos >= stream.start; --pos){
char at_pos = char_to_upper(stream.data[pos]);
if (at_pos == first_char){
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
if (match_insensitive(needle_str, read_str)){
*result = pos;
goto finished;
}
}
}
still_looping = backward_stream_chunk(&stream);
}while (still_looping);
}
}
*result = -1;
finished:;
}
}
inline Buffer_Identifier
buffer_identifier(char *str, int len){
Buffer_Identifier identifier;

View File

@ -72,5 +72,179 @@ end_temp_memory(Temp_Memory temp){
((Partition*)temp.handle)->pos = temp.pos;
}
/*
NOTE(allen):
This is a very week general purpose allocator system.
It should only be used for infrequent large allocations (4K+).
*/
#include <stdint.h>
#include <assert.h>
#include <string.h>
enum{
MEM_BUBBLE_FLAG_INIT = 0x0,
MEM_BUBBLE_USED = 0x1,
};
struct Bubble{
Bubble *prev;
Bubble *next;
int32_t size;
uint32_t flags;
uint32_t _unused_[2];
};
struct General_Memory{
Bubble sentinel;
};
struct Mem_Options{
Partition part;
General_Memory general;
};
inline void
insert_bubble(Bubble *prev, Bubble *bubble){
bubble->prev = prev;
bubble->next = prev->next;
bubble->prev->next = bubble;
bubble->next->prev = bubble;
}
inline void
remove_bubble(Bubble *bubble){
bubble->prev->next = bubble->next;
bubble->next->prev = bubble->prev;
}
static void
general_memory_open(General_Memory *general, void *memory, int32_t size){
general->sentinel.prev = &general->sentinel;
general->sentinel.next = &general->sentinel;
general->sentinel.flags = MEM_BUBBLE_USED;
general->sentinel.size = 0;
Bubble *first = (Bubble*)memory;
first->flags = (uint32_t)MEM_BUBBLE_FLAG_INIT;
first->size = size - sizeof(Bubble);
insert_bubble(&general->sentinel, first);
}
static int32_t
general_memory_check(General_Memory *general){
Bubble *sentinel = &general->sentinel;
for (Bubble *bubble = sentinel->next;
bubble != sentinel;
bubble = bubble->next){
assert(bubble);
Bubble *next = bubble->next;
assert(bubble == next->prev);
if (next != sentinel && bubble->prev != sentinel){
assert(bubble->next > bubble);
assert(bubble > bubble->prev);
char *end_ptr = (char*)(bubble + 1) + bubble->size;
char *next_ptr = (char*)next;
(void)(end_ptr);
(void)(next_ptr);
assert(end_ptr == next_ptr);
}
}
return(1);
}
#define BUBBLE_MIN_SIZE 1024
static void
general_memory_attempt_split(Bubble *bubble, int32_t wanted_size){
int32_t remaining_size = bubble->size - wanted_size;
if (remaining_size >= BUBBLE_MIN_SIZE){
bubble->size = wanted_size;
Bubble *new_bubble = (Bubble*)((char*)(bubble + 1) + wanted_size);
new_bubble->flags = (uint32_t)MEM_BUBBLE_FLAG_INIT;
new_bubble->size = remaining_size - sizeof(Bubble);
insert_bubble(bubble, new_bubble);
}
}
static void*
general_memory_allocate(General_Memory *general, int32_t size){
void *result = 0;
for (Bubble *bubble = general->sentinel.next;
bubble != &general->sentinel;
bubble = bubble->next){
if (!(bubble->flags & MEM_BUBBLE_USED)){
if (bubble->size >= size){
result = bubble + 1;
bubble->flags |= MEM_BUBBLE_USED;
general_memory_attempt_split(bubble, size);
break;
}
}
}
return result;
}
inline void
general_memory_do_merge(Bubble *left, Bubble *right){
assert(left->next == right);
assert(right->prev == left);
left->size += sizeof(Bubble) + right->size;
remove_bubble(right);
}
inline void
general_memory_attempt_merge(Bubble *left, Bubble *right){
if (!(left->flags & MEM_BUBBLE_USED) &&
!(right->flags & MEM_BUBBLE_USED)){
general_memory_do_merge(left, right);
}
}
static void
general_memory_free(General_Memory *general, void *memory){
Bubble *bubble = ((Bubble*)memory) - 1;
bubble->flags &= ~MEM_BUBBLE_USED;
Bubble *prev, *next;
prev = bubble->prev;
next = bubble->next;
general_memory_attempt_merge(bubble, next);
general_memory_attempt_merge(prev, bubble);
}
static void*
general_memory_reallocate(General_Memory *general, void *old, int32_t old_size, int32_t size){
void *result = old;
Bubble *bubble = ((Bubble*)old) - 1;
int32_t additional_space = size - bubble->size;
if (additional_space > 0){
Bubble *next = bubble->next;
if (!(next->flags & MEM_BUBBLE_USED) &&
next->size + sizeof(Bubble) >= additional_space){
general_memory_do_merge(bubble, next);
general_memory_attempt_split(bubble, size);
}
else{
result = general_memory_allocate(general, size);
if (old_size) memcpy(result, old, old_size);
general_memory_free(general, old);
}
}
return result;
}
inline void*
general_memory_reallocate_nocopy(General_Memory *general, void *old, int32_t size){
return general_memory_reallocate(general, old, 0, size);
}
#define reset_temp_memory end_temp_memory
#define gen_struct(g, T) (T*)general_memory_allocate(g, sizeof(T), 0)
#define gen_array(g, T, size) (T*)general_memory_allocate(g, sizeof(T)*(size))
#define gen_block(g, size) general_memory_open(g, size, 0)
#endif

406
4coder_search.cpp Normal file
View File

@ -0,0 +1,406 @@
#ifndef FCODER_SEARCH
#define FCODER_SEARCH
enum Search_Range_Type{
SearchRange_FrontToBack,
SearchRange_BackToFront,
SearchRange_Wave,
};
struct Search_Range{
int type;
int buffer;
int start;
int size;
int mid_start;
int mid_size;
};
struct Search_Set{
Search_Range *ranges;
int count;
int max;
};
struct Search_Iter{
String word;
int pos;
int back_pos;
int i;
int range_initialized;
};
struct Search_Match{
Buffer_Summary buffer;
int start;
int end;
int found_match;
};
// TODO(allen): HOW DO I WANT TO GET MEMORY CUSTOM SIDE??
#define GET_MEMORY(a) (void*)(0)
#define REGET_MEMORY(a,b) (void*)(0)
#define REGET_NOCOPY_MEMORY(a,b) (void*)(0)
#define FREE_MEMORY(a) (void)(a)
static void
search_iter_init(Application_Links *app, Search_Iter *iter, int size){
int str_max = size*2;
if (iter->word.str == 0){
iter->word.str = (char*)GET_MEMORY(str_max);
iter->word.memory_size = str_max;
}
else if (iter->word.memory_size < size){
iter->word.str = (char*)REGET_MEMORY(iter->word.str, str_max);
iter->word.memory_size = str_max;
}
iter->i = 0;
iter->pos = 0;
}
static void
search_set_init(Application_Links *app, Search_Set *set, int range_count){
int max = range_count*2;
if (set->ranges == 0){
set->ranges = (Search_Range*)GET_MEMORY(sizeof(Search_Range)*max);
set->max = max;
}
else if (set->max < range_count){
set->ranges = (Search_Range*)REGET_MEMORY(set->ranges, sizeof(Search_Range)*max);
set->max = max;
}
set->count = range_count;
}
static void
search_hits_table_alloc(Application_Links *app, Table *hits, int table_size){
void *mem = 0;
int mem_size = table_required_mem_size(table_size, sizeof(Offset_String));
if (hits->hash_array == 0){
mem = GET_MEMORY(mem_sze);
}
else{
mem = REGET_NOCOPY_MEMORY(hits->hash_array, mem_sze);
}
table_init_memory(hits, mem, table_size, sizeof(Offset_String));
}
static void
search_hits_init(Application_Links *app, Table *hits, String_Space *str, int table_size, int str_size){
if (hits->hash_array == 0){
search_hits_table_alloc(app, hits, table_size);
}
else{
int mem_size = table_required_mem_size(table_size, sizeof(Offset_String));
void *mem = REGET_NOCOPY_MEMORY(mem, mem_size);
table_init_memory(hits, mem, table_size, sizeof(Offset_String));
}
if (str->space == 0){
str->space = (char*)GET_MEMORY(str_size);
str->max = str_size;
}
else if (str->max < str_size){
str->space = (char*)REGET_NOCOPY_MEMORY(str->space, str_size);
str->max = str_size;
}
str->pos = str->new_pos = 0;
table_clear(hits);
}
static int
search_hit_add(Application_Links *app, Table *hits, String_Space *space, char *str, int len){
int result = false;
assert(len != 0);
Offset_String ostring = strspace_append(space, str, len);
if (ostring.size == 0){
int new_size = space->max*2;
if (new_size < space->max + len){
new_size = space->max + len;
}
space->space = (char*)REGET_MEMORY(space->space, new_size);
ostring = strspace_append(space, str, len);
}
assert(ostring.size != 0);
if (table_at_capacity(hits)){
Table new_hits = {0};
search_hits_table_alloc(app, &new_hits, hits->max*2);
table_clear(&new_hits);
table_rehash(hits, &new_hits, space->space, tbl_offset_string_hash, tbl_offset_string_compare);
FREE_MEMORY(hits->hash_array);
*hits = new_hits;
}
if (!table_add(hits, &ostring, space->space, tbl_offset_string_hash, tbl_offset_string_compare)){
result = true;
strspace_keep_prev(space);
}
else{
strspace_discard_prev(space);
}
return(result);
}
static int
buffer_seek_alpha_numeric_end(Application_Links *app, Buffer_Summary *buffer, int pos){
char space[1024];
Stream_Chunk chunk = {0};
if (init_stream_chunk(&chunk, app, buffer, pos, space, sizeof(space))){
int still_looping = true;
do{
for (; pos < chunk.end; ++pos){
char at_pos = chunk.data[pos];
if (!char_is_alpha_numeric(at_pos)) goto double_break;
}
still_looping = forward_stream_chunk(&chunk);
}while(still_looping);
}
double_break:;
return(pos);
}
static void
search_iter_next_range(Search_Iter *it){
++it->i;
it->pos = 0;
it->back_pos = 0;
it->range_initialized = 0;
}
enum{
FindResult_None,
FindResult_FoundMatch,
FindResult_PastEnd
};
static int
search_front_to_back_step(Application_Links *app,
Search_Range *range,
String word,
int *pos,
Search_Match *result_ptr){
int found_match = FindResult_None;
Search_Match result = *result_ptr;
int end_pos = range->start + range->size;
if (*pos + word.size < end_pos){
int start_pos = *pos;
if (start_pos < range->start){
start_pos = range->start;
}
result.buffer = app->get_buffer(app, range->buffer, AccessAll);
buffer_seek_string_forward(app, &result.buffer,
start_pos, end_pos,
word.str, word.size,
&result.start);
if (result.start < end_pos){
*pos = result.start + 1;
char prev = ' ';
if (result.start > 0){
prev = buffer_get_char(app, &result.buffer, result.start - 1);
}
if (!char_is_alpha_numeric(prev)){
result.end =
buffer_seek_alpha_numeric_end(
app, &result.buffer, result.start);
if (result.end < end_pos){
result.found_match = true;
*pos = result.end;
found_match = FindResult_FoundMatch;
}
}
}
else{
found_match = FindResult_PastEnd;
}
}
else{
found_match = FindResult_PastEnd;
}
*result_ptr = result;
return(found_match);
}
static int
search_back_to_front_step(Application_Links *app,
Search_Range *range,
String word,
int *pos,
Search_Match *result_ptr){
int found_match = FindResult_None;
Search_Match result = *result_ptr;
int end_pos = range->start + range->size;
if (*pos > range->start){
int start_pos = *pos;
result.buffer = app->get_buffer(app, range->buffer, AccessAll);
buffer_seek_string_backward(app, &result.buffer,
start_pos, range->start,
word.str, word.size,
&result.start);
if (result.start >= range->start){
*pos = result.start - 1;
char prev = ' ';
if (result.start > 0){
prev = buffer_get_char(app, &result.buffer, result.start - 1);
}
if (!char_is_alpha_numeric(prev)){
result.end =
buffer_seek_alpha_numeric_end(
app, &result.buffer, result.start);
if (result.end < end_pos){
result.found_match = true;
*pos = result.start - word.size;
found_match = FindResult_FoundMatch;
}
}
}
else{
found_match = FindResult_PastEnd;
}
}
else{
found_match = FindResult_PastEnd;
}
*result_ptr = result;
return(found_match);
}
static Search_Match
search_next_match(Application_Links *app, Search_Set *set, Search_Iter *it_ptr){
Search_Match result = {0};
Search_Iter iter = *it_ptr;
char *spare = (char*)GET_MEMORY(iter.word.size);
int count = set->count;
for (; iter.i < count;){
Search_Range *range = set->ranges + iter.i;
int find_result = FindResult_None;
if (!iter.range_initialized){
iter.range_initialized = true;
switch (range->type){
case SearchRange_BackToFront:
{
iter.back_pos = range->start+range->size-1;
}break;
case SearchRange_Wave:
{
iter.back_pos = range->mid_start-1;
iter.pos = range->mid_start + range->mid_size;
}break;
}
}
switch (range->type){
case SearchRange_FrontToBack:
{
find_result =
search_front_to_back_step(app, range,
iter.word,
&iter.pos,
&result);
}break;
case SearchRange_BackToFront:
{
find_result =
search_back_to_front_step(app, range,
iter.word,
&iter.back_pos,
&result);
}break;
case SearchRange_Wave:
{
Search_Match forward_match = {0};
int forward_result =
search_front_to_back_step(app, range,
iter.word,
&iter.pos,
&forward_match);
Search_Match backward_match = {0};
int backward_result =
search_back_to_front_step(app, range,
iter.word,
&iter.back_pos,
&backward_match);
if (forward_result == FindResult_FoundMatch){
if (backward_result == FindResult_FoundMatch){
find_result = FindResult_FoundMatch;
int forward_start = range->mid_start + range->mid_size;
int forward_distance = (forward_match.start - forward_start);
int backward_distance = (forward_match.end - range->mid_start);
if (backward_distance < forward_distance){
--iter.pos;
result = forward_match;
}
else{
++iter.back_pos;
result = backward_match;
}
}
else{
find_result = FindResult_FoundMatch;
result = forward_match;
}
}
else{
if (backward_result == FindResult_FoundMatch){
find_result = FindResult_FoundMatch;
result = backward_match;
--iter.pos;
}
else{
find_result = FindResult_PastEnd;
}
}
}break;
}
if (find_result == FindResult_FoundMatch){
goto double_break;
}
else if (find_result == FindResult_PastEnd){
search_iter_next_range(&iter);
}
}
double_break:;
FREE_MEMORY(spare);
*it_ptr = iter;
return(result);
}
#endif

View File

@ -3,7 +3,7 @@
*
* 14.02.2016
*
* 4tech C style genereic hash table
* C style genereic hash table
*
*/
@ -13,57 +13,57 @@
#define TableHashDeleted 1
#define TableHashMin 0x10000000
typedef u32 Hash_Function(void *item, void *arg);
typedef i32 Compare_Function(void *key, void *item, void *arg);
#include <stdint.h>
#include <assert.h>
#include <string.h>
typedef uint32_t Hash_Function(void *item, void *arg);
typedef int32_t Compare_Function(void *key, void *item, void *arg);
struct Table{
u32 *hash_array;
u8 *data_array;
i32 count, max;
i32 item_size;
uint32_t *hash_array;
char *data_array;
int32_t count, max;
int32_t item_size;
};
internal i32
table_required_mem_size(i32 table_size, i32 item_size){
i32 mem_size, hash_size;
hash_size = ((table_size * sizeof(u32)) + 7) & ~7;
mem_size = hash_size + table_size * item_size;
static int32_t
table_required_mem_size(int32_t table_size, int32_t item_size){
int32_t hash_size = ((table_size * sizeof(uint32_t)) + 7) & ~7;
int32_t mem_size = hash_size + table_size * item_size;
return(mem_size);
}
internal void
table_init_memory(Table *table, void *memory, i32 table_size, i32 item_size){
i32 hash_size = table_size * sizeof(u32);
static void
table_init_memory(Table *table, void *memory, int32_t table_size, int32_t item_size){
int32_t hash_size = table_size * sizeof(uint32_t);
hash_size = (hash_size + 7) & ~7;
table->hash_array = (u32*)memory;
table->data_array = (u8*)(table->hash_array) + hash_size;
table->hash_array = (uint32_t*)memory;
table->data_array = (char*)(table->hash_array) + hash_size;
table->count = 0;
table->max = table_size;
table->item_size = item_size;
}
internal b32
static int32_t
table_at_capacity(Table *table){
b32 result = 1;
int32_t result = true;
if (table->count * 8 < table->max * 7){
result = 0;
result = false;
}
return(result);
}
internal b32
static int32_t
table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
u32 hash, *inspect;
i32 i, start;
assert(table->count * 8 < table->max * 7);
Assert(table->count * 8 < table->max * 7);
hash = (hash_func(item, arg) | TableHashMin);
i = hash % table->max;
start = i;
inspect = table->hash_array + i;
uint32_t hash = (hash_func(item, arg) | TableHashMin);
int32_t i = hash % table->max;
int32_t start = i;
uint32_t *inspect = table->hash_array + i;
while (*inspect >= TableHashMin){
if (*inspect == hash){
@ -77,7 +77,7 @@ table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare
i = 0;
inspect = table->hash_array;
}
Assert(i != start);
assert(i != start);
}
*inspect = hash;
memcpy(table->data_array + i*table->item_size, item, table->item_size);
@ -86,17 +86,14 @@ table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare
return(0);
}
internal b32
table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index, Hash_Function *hash_func, Compare_Function *comp_func){
u32 hash, *inspect;
i32 i, start;
static int32_t
table_find_pos(Table *table, void *search_key, void *arg, int32_t *pos, int32_t *index, Hash_Function *hash_func, Compare_Function *comp_func){
assert((table->count - 1) * 8 < table->max * 7);
Assert((table->count - 1) * 8 < table->max * 7);
hash = (hash_func(search_key, arg) | TableHashMin);
i = hash % table->max;
start = i;
inspect = table->hash_array + i;
uint32_t hash = (hash_func(search_key, arg) | TableHashMin);
int32_t i = hash % table->max;
int32_t start = i;
uint32_t *inspect = table->hash_array + i;
while (*inspect != TableHashEmpty){
if (*inspect == hash){
@ -120,8 +117,8 @@ table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index,
inline void*
table_find_item(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 pos;
void *result = 0;
int32_t pos;
if (table_find_pos(table, search_key, arg, &pos, 0, hash_func, comp_func)){
result = table->data_array + pos;
}
@ -129,18 +126,18 @@ table_find_item(Table *table, void *search_key, void *arg, Hash_Function *hash_f
}
inline void
table_remove_index(Table *table, i32 index){
table_remove_index(Table *table, int32_t index){
table->hash_array[index] = TableHashDeleted;
--table->count;
}
inline b32
inline int32_t
table_remove_match(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 index;
b32 result = 0;
int32_t result = false;
int32_t index;
if (table_find_pos(table, search_key, arg, 0, &index, hash_func, comp_func)){
table_remove_index(table, index);
result = 1;
result = true;
}
return(result);
}
@ -151,20 +148,18 @@ table_clear(Table *table){
memset(table->hash_array, 0, table->max*sizeof(*table->hash_array));
}
internal void
static void
table_rehash(Table *src, Table *dst, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 i, c, count, item_size;
u32 *hash_item;
u8 *data_item;
assert((dst->count + src->count - 1) * 7 < dst->max * 8);
assert(dst->item_size == src->item_size);
Assert((dst->count + src->count - 1) * 7 < dst->max * 8);
Assert(dst->item_size == src->item_size);
count = src->count;
hash_item = src->hash_array;
data_item = src->data_array;
item_size = src->item_size;
for (i = 0, c = 0; c < count; ++i, ++hash_item, data_item += item_size){
int32_t count = src->count;
int32_t item_size = src->item_size;
uint32_t *hash_item = src->hash_array;
char *data_item = src->data_array;
for (int32_t i = 0, c = 0;
c < count;
++i, ++hash_item, data_item += item_size){
if (*hash_item >= TableHashMin){
++c;
table_add(dst, data_item, arg, hash_func, comp_func);
@ -172,12 +167,12 @@ table_rehash(Table *src, Table *dst, void *arg, Hash_Function *hash_func, Compar
}
}
internal u32
static uint32_t
tbl_string_hash(void *item, void *arg){
String *string = (String*)item;
char *str;
i32 i,len;
u32 x = 5381;
int32_t i,len;
uint32_t x = 5381;
char c;
(void)arg;
@ -192,20 +187,20 @@ tbl_string_hash(void *item, void *arg){
return(x);
}
internal i32
static int32_t
tbl_string_compare(void *a, void *b, void *arg){
String *stra = (String*)a;
String *strb = (String*)b;
i32 result = !match(*stra, *strb);
int32_t result = !match(*stra, *strb);
return(result);
}
internal u32
static uint32_t
tbl_offset_string_hash(void *item, void *arg){
Offset_String *string = (Offset_String*)item;
char *str;
i32 i,len;
u32 x = 5381;
int32_t i,len;
uint32_t x = 5381;
char c;
str = ((char*)arg) + string->offset;
@ -219,23 +214,23 @@ tbl_offset_string_hash(void *item, void *arg){
return(x);
}
internal i32
static int32_t
tbl_offset_string_compare(void *a, void *b, void *arg){
Offset_String *ostra = (Offset_String*)a;
Offset_String *ostrb = (Offset_String*)b;
String stra = make_string((char*)arg + ostra->offset, ostra->size);
String strb = make_string((char*)arg + ostrb->offset, ostrb->size);
i32 result = !match(stra, strb);
int32_t result = !match(stra, strb);
return(result);
}
struct String_Space{
char *space;
i32 pos, new_pos, max;
int32_t pos, new_pos, max;
};
internal Offset_String
strspace_append(String_Space *space, char *str, i32 len){
static Offset_String
strspace_append(String_Space *space, char *str, int32_t len){
Offset_String result = {};
if (space->new_pos + len <= space->max){
result.offset = space->new_pos;
@ -247,12 +242,12 @@ strspace_append(String_Space *space, char *str, i32 len){
return(result);
}
internal void
static void
strspace_keep_prev(String_Space *space){
space->pos = space->new_pos;
}
internal void
static void
strspace_discard_prev(String_Space *space){
space->new_pos = space->pos;
}

View File

@ -98,6 +98,16 @@ ENUM(uint64_t, Command_ID){
cmdid_count
};
/* DOC(TODO) */
FLAGENUM(Memory_Protect_Flags){
/* DOC(TODO) */
MemProtect_Read = 0x1,
/* DOC(TODO) */
MemProtect_Write = 0x2,
/* DOC(TODO) */
MemProtect_Execute = 0x4,
};
/* DOC(User_Input_Type_ID specifies a type of user input event.) */
ENUM(int32_t, User_Input_Type_ID){
/* DOC(UserInputNone indicates that no event has occurred.) */

View File

@ -472,6 +472,7 @@ COMMAND_DECL(word_complete){
complete_state->word_end = word_start + match_size;
complete_state->set.ranges[1].start = word_start + match_size;
end_temp_memory(temp);
break;
}
end_temp_memory(temp);

View File

@ -338,6 +338,28 @@ DOC_SEE(Command_Line_Input_Flag)
return(result);
}
API_EXPORT void*
Memory_Alloc(Application_Links *app, int32_t size)/*
DOC(TODO)
*/{
void *result = 0;
return(result);
}
API_EXPORT int32_t
Memory_Set_Protection(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags)/*
DOC(TODO)
*/{
int32_t result = 0;
return(result);
}
API_EXPORT void
Memory_Free(Application_Links *app, void *mem)/*
DOC(TODO)
*/{
}
API_EXPORT void
Clipboard_Post(Application_Links *app, int32_t clipboard_id, char *str, int32_t len)/*
DOC_PARAM(clipboard_id, This parameter is set up to prepare for future features, it should always be 0 for now.)
@ -405,6 +427,16 @@ DOC_SEE(The_4coder_Clipboard)
return(size);
}
API_EXPORT int32_t
Get_Buffer_Count(Application_Links *app)/*
DOC(TODO)
*/{
Command_Data *cmd = (Command_Data*)app->cmd_context;
Working_Set *working_set = &cmd->models->working_set;
int32_t result = working_set->file_count;
return(result);
}
internal void
internal_get_buffer_first(Working_Set *working_set, Buffer_Summary *buffer){
if (working_set->file_count > 0){
@ -710,7 +742,7 @@ DOC_PARAM(edits, This parameter provides about the source string and destination
DOC_PARAM(edit_count, This parameter specifies the number of Buffer_Edit structs in edits.)
DOC_PARAM(type, This prameter specifies what type of batch edit to execute.)
DOC_RETURN(This call returns non-zero if the batch edit succeeds.)
DOC()
DOC(TODO)
DOC_SEE(Buffer_Edit)
DOC_SEE(Buffer_Batch_Edit_Type)
*/{

View File

@ -19,14 +19,13 @@
#define FSTRING_IMPLEMENTATION
#include "4coder_string.h"
#include "4ed_mem.cpp"
#include "4ed_math.cpp"
#include "4ed_system.h"
#include "4ed_rendering.h"
#include "4ed.h"
#include "4tech_table.cpp"
#include "4coder_table.cpp"
#define FCPP_LEXER_IMPLEMENTATION
//#include "test/4cpp_new_lexer.h"

View File

@ -528,7 +528,7 @@ working_set_init(Working_Set *working_set, Partition *partition, General_Memory
table_size = working_set->file_max;
mem_size = table_required_mem_size(table_size, item_size);
mem = general_memory_allocate(general, mem_size, 0);
mem = general_memory_allocate(general, mem_size);
memset(mem, 0, mem_size);
table_init_memory(&working_set->table, mem, table_size, item_size);
}
@ -542,7 +542,7 @@ working_set__grow_if_needed(Table *table, General_Memory *general, void *arg, Ha
if (table_at_capacity(table)){
new_max = table->max * 2;
mem_size = table_required_mem_size(new_max, table->item_size);
mem = general_memory_allocate(general, mem_size, 0);
mem = general_memory_allocate(general, mem_size);
table_init_memory(&btable, mem, new_max, table->item_size);
table_clear(&btable);
table_rehash(table, &btable, 0, hash_func, comp_func);

View File

@ -848,7 +848,7 @@ file_save(System_Functions *system, Mem_Options *mem, Editing_File *file, char *
if (!data){
used_general = 1;
data = (char*)general_memory_allocate(&mem->general, max, 0);
data = (char*)general_memory_allocate(&mem->general, max);
}
}
Assert(data);
@ -885,23 +885,12 @@ file_save_and_set_names(System_Functions *system, Mem_Options *mem,
return result;
}
enum File_Bubble_Type{
BUBBLE_BUFFER = 1,
BUBBLE_STARTS,
BUBBLE_WIDTHS,
BUBBLE_WRAPS,
BUBBLE_TOKENS,
BUBBLE_UNDO_STRING,
BUBBLE_UNDO,
BUBBLE_UNDO_CHILDREN,
//
FILE_BUBBLE_TYPE_END,
enum{
GROW_FAILED,
GROW_NOT_NEEDED,
GROW_SUCCESS,
};
#define GROW_FAILED 0
#define GROW_NOT_NEEDED 1
#define GROW_SUCCESS 2
internal i32
file_grow_starts_widths_as_needed(General_Memory *general, Buffer_Type *buffer, i32 additional_lines){
b32 result = GROW_NOT_NEEDED;
@ -915,11 +904,11 @@ file_grow_starts_widths_as_needed(General_Memory *general, Buffer_Type *buffer,
f32 *new_widths = (f32*)general_memory_reallocate(
general, buffer->line_widths,
sizeof(f32)*count, sizeof(f32)*max, BUBBLE_WIDTHS);
sizeof(f32)*count, sizeof(f32)*max);
i32 *new_lines = (i32*)general_memory_reallocate(
general, buffer->line_starts,
sizeof(i32)*count, sizeof(i32)*max, BUBBLE_STARTS);
sizeof(i32)*count, sizeof(i32)*max);
if (new_lines){
buffer->line_starts = new_lines;
@ -945,13 +934,13 @@ file_measure_starts_widths(System_Functions *system, General_Memory *general,
Buffer_Type *buffer, float *advance_data){
if (!buffer->line_starts){
i32 max = buffer->line_max = Kbytes(1);
buffer->line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32), BUBBLE_STARTS);
buffer->line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32));
TentativeAssert(buffer->line_starts);
// TODO(allen): when unable to allocate?
}
if (!buffer->line_widths){
i32 max = buffer->widths_max = Kbytes(1);
buffer->line_widths = (f32*)general_memory_allocate(general, max*sizeof(f32), BUBBLE_WIDTHS);
buffer->line_widths = (f32*)general_memory_allocate(general, max*sizeof(f32));
TentativeAssert(buffer->line_starts);
// TODO(allen): when unable to allocate?
}
@ -964,7 +953,7 @@ file_measure_starts_widths(System_Functions *system, General_Memory *general,
{
i32 *new_lines = (i32*)general_memory_reallocate(
general, buffer->line_starts, sizeof(i32)*count, sizeof(i32)*max, BUBBLE_STARTS);
general, buffer->line_starts, sizeof(i32)*count, sizeof(i32)*max);
// TODO(allen): when unable to grow?
TentativeAssert(new_lines);
@ -975,7 +964,7 @@ file_measure_starts_widths(System_Functions *system, General_Memory *general,
{
f32 *new_lines = (f32*)
general_memory_reallocate(general, buffer->line_widths,
sizeof(f32)*count, sizeof(f32)*max, BUBBLE_WIDTHS);
sizeof(f32)*count, sizeof(f32)*max);
// TODO(allen): when unable to grow?
TentativeAssert(new_lines);
@ -999,11 +988,11 @@ view_measure_wraps(General_Memory *general, View *view){
i32 max = view->file_data.line_max = LargeRoundUp(line_count, Kbytes(1));
if (view->file_data.line_wrap_y){
view->file_data.line_wrap_y = (f32*)
general_memory_reallocate_nocopy(general, view->file_data.line_wrap_y, sizeof(f32)*max, BUBBLE_WRAPS);
general_memory_reallocate_nocopy(general, view->file_data.line_wrap_y, sizeof(f32)*max);
}
else{
view->file_data.line_wrap_y = (f32*)
general_memory_allocate(general, sizeof(f32)*max, BUBBLE_WRAPS);
general_memory_allocate(general, sizeof(f32)*max);
}
}
@ -1033,7 +1022,7 @@ file_create_from_string(System_Functions *system, Models *models,
page_size = buffer_init_page_size(&init);
page_size = LargeRoundUp(page_size, Kbytes(4));
if (page_size < Kbytes(4)) page_size = Kbytes(4);
void *data = general_memory_allocate(general, page_size, BUBBLE_BUFFER);
void *data = general_memory_allocate(general, page_size);
buffer_init_provide_page(&init, data, page_size);
}
@ -1064,24 +1053,24 @@ file_create_from_string(System_Functions *system, Models *models,
// TODO(allen): Redo undo system (if you don't mind the pun)
i32 request_size = Kbytes(64);
file->state.undo.undo.max = request_size;
file->state.undo.undo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING);
file->state.undo.undo.strings = (u8*)general_memory_allocate(general, request_size);
file->state.undo.undo.edit_max = request_size / sizeof(Edit_Step);
file->state.undo.undo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO);
file->state.undo.undo.edits = (Edit_Step*)general_memory_allocate(general, request_size);
file->state.undo.redo.max = request_size;
file->state.undo.redo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING);
file->state.undo.redo.strings = (u8*)general_memory_allocate(general, request_size);
file->state.undo.redo.edit_max = request_size / sizeof(Edit_Step);
file->state.undo.redo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO);
file->state.undo.redo.edits = (Edit_Step*)general_memory_allocate(general, request_size);
file->state.undo.history.max = request_size;
file->state.undo.history.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING);
file->state.undo.history.strings = (u8*)general_memory_allocate(general, request_size);
file->state.undo.history.edit_max = request_size / sizeof(Edit_Step);
file->state.undo.history.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO);
file->state.undo.history.edits = (Edit_Step*)general_memory_allocate(general, request_size);
file->state.undo.children.max = request_size;
file->state.undo.children.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING);
file->state.undo.children.strings = (u8*)general_memory_allocate(general, request_size);
file->state.undo.children.edit_max = request_size / sizeof(Buffer_Edit);
file->state.undo.children.edits = (Buffer_Edit*)general_memory_allocate(general, request_size, BUBBLE_UNDO);
file->state.undo.children.edits = (Buffer_Edit*)general_memory_allocate(general, request_size);
file->state.undo.history_block_count = 1;
file->state.undo.history_head_block = 0;
@ -1253,7 +1242,7 @@ Job_Callback_Sig(job_full_lex){
{
Assert(file->state.swap_stack.tokens == 0);
file->state.swap_stack.tokens = (Cpp_Token*)
general_memory_allocate(general, new_max*sizeof(Cpp_Token), BUBBLE_TOKENS);
general_memory_allocate(general, new_max*sizeof(Cpp_Token));
}
system->release_lock(FRAME_LOCK);
@ -1368,7 +1357,7 @@ file_relex_parallel(System_Functions *system,
stack->tokens = (Cpp_Token*)
general_memory_reallocate(general, stack->tokens,
stack->count*sizeof(Cpp_Token),
new_max*sizeof(Cpp_Token), BUBBLE_TOKENS);
new_max*sizeof(Cpp_Token));
stack->max_count = new_max;
}
@ -2109,7 +2098,7 @@ file_do_single_edit(System_Functions *system,
part->base + part->pos, scratch_size, &request_amount)){
void *new_data = 0;
if (request_amount > 0){
new_data = general_memory_allocate(general, request_amount, BUBBLE_BUFFER);
new_data = general_memory_allocate(general, request_amount);
}
void *old_data = buffer_edit_provide_memory(&file->state.buffer, new_data, request_amount);
if (old_data) general_memory_free(general, old_data);
@ -2185,7 +2174,7 @@ file_do_white_batch_edit(System_Functions *system, Models *models, Editing_File
scratch_size, &request_amount)){
void *new_data = 0;
if (request_amount > 0){
new_data = general_memory_allocate(general, request_amount, BUBBLE_BUFFER);
new_data = general_memory_allocate(general, request_amount);
}
void *old_data = buffer_edit_provide_memory(&file->state.buffer, new_data, request_amount);
if (old_data) general_memory_free(general, old_data);
@ -2258,6 +2247,7 @@ file_clear(System_Functions *system, Models *models, Editing_File *file){
file_replace_range(system, models, file, 0, buffer_size(&file->state.buffer), 0, 0);
}
// TODO(allen): get rid of this
inline void
view_replace_range(System_Functions *system, Models *models, View *view,
i32 start, i32 end, char *str, i32 len){
@ -3116,6 +3106,17 @@ view_show_file(View *view){
}
}
internal String
make_string_terminated(Partition *part, char *str, i32 len){
char *space = (char*)push_array(part, char, len + 1);
String string = make_string(str, len, len+1);
copy_fast_unsafe(space, string);
string.str = space;
terminate_with_null(&string);
return(string);
}
internal void
view_save_file(System_Functions *system, Models *models,
Editing_File *file, View *view, String filename, b32 save_as){
@ -4774,8 +4775,6 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
append_int_to_str(&string, bubble->size);
append_padding(&string, ' ', 40);
append(&string, " type: ");
append_int_to_str(&string, bubble->type);
gui_do_text_field(target, string, empty_str);
}
}break;
@ -6011,12 +6010,12 @@ search_iter_init(General_Memory *general, Search_Iter *iter, i32 size){
if (iter->word.str == 0){
str_max = size*2;
iter->word.str = (char*)general_memory_allocate(general, str_max, 0);
iter->word.str = (char*)general_memory_allocate(general, str_max);
iter->word.memory_size = str_max;
}
else if (iter->word.memory_size < size){
str_max = size*2;
iter->word.str = (char*)general_memory_reallocate_nocopy(general, iter->word.str, str_max, 0);
iter->word.str = (char*)general_memory_reallocate_nocopy(general, iter->word.str, str_max);
iter->word.memory_size = str_max;
}
@ -6030,13 +6029,13 @@ search_set_init(General_Memory *general, Search_Set *set, i32 set_count){
if (set->ranges == 0){
max = set_count*2;
set->ranges = (Search_Range*)general_memory_allocate(general, sizeof(Search_Range)*max, 0);
set->ranges = (Search_Range*)general_memory_allocate(general, sizeof(Search_Range)*max);
set->max = max;
}
else if (set->max < set_count){
max = set_count*2;
set->ranges = (Search_Range*)general_memory_reallocate_nocopy(
general, set->ranges, sizeof(Search_Range)*max, 0);
general, set->ranges, sizeof(Search_Range)*max);
set->max = max;
}
@ -6050,10 +6049,10 @@ search_hits_table_alloc(General_Memory *general, Table *hits, i32 table_size){
mem_size = table_required_mem_size(table_size, sizeof(Offset_String));
if (hits->hash_array == 0){
mem = general_memory_allocate(general, mem_size, 0);
mem = general_memory_allocate(general, mem_size);
}
else{
mem = general_memory_reallocate_nocopy(general, hits->hash_array, mem_size, 0);
mem = general_memory_reallocate_nocopy(general, hits->hash_array, mem_size);
}
table_init_memory(hits, mem, table_size, sizeof(Offset_String));
}
@ -6068,16 +6067,16 @@ search_hits_init(General_Memory *general, Table *hits, String_Space *str, i32 ta
}
else if (hits->max < table_size){
mem_size = table_required_mem_size(table_size, sizeof(Offset_String));
mem = general_memory_reallocate_nocopy(general, hits->hash_array, mem_size, 0);
mem = general_memory_reallocate_nocopy(general, hits->hash_array, mem_size);
table_init_memory(hits, mem, table_size, sizeof(Offset_String));
}
if (str->space == 0){
str->space = (char*)general_memory_allocate(general, str_size, 0);
str->space = (char*)general_memory_allocate(general, str_size);
str->max = str_size;
}
else if (str->max < str_size){
str->space = (char*)general_memory_reallocate_nocopy(general, str->space, str_size, 0);
str->space = (char*)general_memory_reallocate_nocopy(general, str->space, str_size);
str->max = str_size;
}
@ -6097,7 +6096,7 @@ search_hit_add(General_Memory *general, Table *hits, String_Space *space, char *
ostring = strspace_append(space, str, len);
if (ostring.size == 0){
new_size = Max(space->max*2, space->max + len);
space->space = (char*)general_memory_reallocate(general, space->space, space->new_pos, new_size, 0);
space->space = (char*)general_memory_reallocate(general, space->space, space->new_pos, new_size);
ostring = strspace_append(space, str, len);
}
@ -6210,7 +6209,7 @@ live_set_alloc_view(Live_Views *live_set, Panel *panel, Models *models){
{
i32 gui_mem_size = Kbytes(32);
void *gui_mem = general_memory_allocate(&models->mem.general, gui_mem_size + 8, 0);
void *gui_mem = general_memory_allocate(&models->mem.general, gui_mem_size + 8);
result.view->gui_mem = gui_mem;
gui_mem = advance_to_alignment(gui_mem);
result.view->gui_target.push = make_part(gui_mem, gui_mem_size);

View File

@ -1,205 +0,0 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 13.11.2015
*
* Memory utils for 4coder
*
*/
// TOP
enum Memory_Bubble_Flag{
MEM_BUBBLE_USED = 0x1,
MEM_BUBBLE_DEBUG = 0xD3000000,
MEM_BUBBLE_SYS_DEBUG = 0x5D000000,
MEM_BUBBLE_DEBUG_MASK = 0xFF000000
};
struct Bubble{
Bubble *prev;
Bubble *next;
u32 flags;
i32 size;
u32 type;
u32 _unused_;
};
struct General_Memory{
Bubble sentinel;
};
struct Mem_Options{
Partition part;
General_Memory general;
};
inline void
insert_bubble(Bubble *prev, Bubble *bubble){
bubble->prev = prev;
bubble->next = prev->next;
bubble->prev->next = bubble;
bubble->next->prev = bubble;
}
inline void
remove_bubble(Bubble *bubble){
bubble->prev->next = bubble->next;
bubble->next->prev = bubble->prev;
}
#if FRED_INTERNAL
#define MEM_BUBBLE_FLAG_INIT MEM_BUBBLE_DEBUG
#else
#define MEM_BUBBLE_FLAG_INIT 0
#endif
internal void
general_memory_open(General_Memory *general, void *memory, i32 size){
general->sentinel.prev = &general->sentinel;
general->sentinel.next = &general->sentinel;
general->sentinel.flags = MEM_BUBBLE_USED;
general->sentinel.size = 0;
Bubble *first = (Bubble*)memory;
first->flags = (u32)MEM_BUBBLE_FLAG_INIT;
first->size = size - sizeof(Bubble);
insert_bubble(&general->sentinel, first);
}
internal b32
general_memory_check(General_Memory *general){
Bubble *sentinel = &general->sentinel;
for (Bubble *bubble = sentinel->next;
bubble != sentinel;
bubble = bubble->next){
Assert(bubble);
Bubble *next = bubble->next;
Assert(bubble == next->prev);
if (next != sentinel && bubble->prev != sentinel){
Assert(bubble->next > bubble);
Assert(bubble > bubble->prev);
char *end_ptr = (char*)(bubble + 1) + bubble->size;
char *next_ptr = (char*)next;
AllowLocal(end_ptr);
AllowLocal(next_ptr);
Assert(end_ptr == next_ptr);
}
}
return(1);
}
#define BUBBLE_MIN_SIZE 1024
internal void
general_memory_attempt_split(Bubble *bubble, i32 wanted_size){
i32 remaining_size = bubble->size - wanted_size;
if (remaining_size >= BUBBLE_MIN_SIZE){
bubble->size = wanted_size;
Bubble *new_bubble = (Bubble*)((u8*)(bubble + 1) + wanted_size);
new_bubble->flags = (u32)MEM_BUBBLE_FLAG_INIT;
new_bubble->size = remaining_size - sizeof(Bubble);
insert_bubble(bubble, new_bubble);
}
}
internal void*
general_memory_allocate(General_Memory *general, i32 size, u32 type = 0){
void *result = 0;
for (Bubble *bubble = general->sentinel.next;
bubble != &general->sentinel;
bubble = bubble->next){
if (!(bubble->flags & MEM_BUBBLE_USED)){
if (bubble->size >= size){
result = bubble + 1;
bubble->flags |= MEM_BUBBLE_USED;
bubble->type = type;
general_memory_attempt_split(bubble, size);
break;
}
}
}
return result;
}
inline void
general_memory_do_merge(Bubble *left, Bubble *right){
Assert(left->next == right);
Assert(right->prev == left);
left->size += sizeof(Bubble) + right->size;
remove_bubble(right);
}
inline void
general_memory_attempt_merge(Bubble *left, Bubble *right){
if (!(left->flags & MEM_BUBBLE_USED) &&
!(right->flags & MEM_BUBBLE_USED)){
general_memory_do_merge(left, right);
}
}
internal void
general_memory_free(General_Memory *general, void *memory){
Bubble *bubble = ((Bubble*)memory) - 1;
#if FRED_INTERNAL
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
#endif
bubble->flags &= ~MEM_BUBBLE_USED;
bubble->type = 0;
Bubble *prev, *next;
prev = bubble->prev;
next = bubble->next;
general_memory_attempt_merge(bubble, next);
general_memory_attempt_merge(prev, bubble);
}
internal void*
general_memory_reallocate(General_Memory *general, void *old, i32 old_size, i32 size, u32 type = 0){
void *result = old;
Bubble *bubble = ((Bubble*)old) - 1;
bubble->type = type;
#if FRED_INTERNAL
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
#endif
i32 additional_space = size - bubble->size;
if (additional_space > 0){
Bubble *next = bubble->next;
if (!(next->flags & MEM_BUBBLE_USED) &&
next->size + sizeof(Bubble) >= additional_space){
general_memory_do_merge(bubble, next);
general_memory_attempt_split(bubble, size);
}
else{
result = general_memory_allocate(general, size, type);
if (old_size) memcpy(result, old, old_size);
general_memory_free(general, old);
}
}
return result;
}
inline void*
general_memory_reallocate_nocopy(General_Memory *general, void *old, i32 size, u32 type = 0){
return general_memory_reallocate(general, old, 0, size, type);
}
#define reset_temp_memory end_temp_memory
#define gen_struct(g, T) (T*)general_memory_allocate(g, sizeof(T), 0)
#define gen_array(g, T, size) (T*)general_memory_allocate(g, sizeof(T)*(size), 0)
#define gen_block(g, size) general_memory_open(g, size, 0)
internal String
make_string_terminated(Partition *part, char *str, int len){
char *space = (char*)push_array(part, char, len + 1);
String string = make_string(str, len, len+1);
copy_fast_unsafe(space, string);
string.str = space;
terminate_with_null(&string);
return(string);
}
// BOTTOM

View File

@ -174,24 +174,24 @@
; [] tutorials
; [] 4edT thing
; [] unicode/UTF support
; [] console emulator
;
; INTERNAL TODOS
; [X] switch building non-extensible version by statically linking to custom.cpp
; [X] pack fonts more squarely
; [] general parameter handling
; [X] change job canceling to a polling based thing
; [] hashed string pool for clipboard/filenames/etc
; [] new profiling/debugging system
; [] change job canceling to a polling based thing
;
; EASY TODOS
; [X] better messages for example not "BEHIND OS"
; [X] shift backspace
; [X] center view on cursor
; [X] delta time in scroll interpolation
; [] close editor command
; [] panel grow/shrink commands
; [] delta time in scroll interpolation
;
; HARD BUGS
@ -200,13 +200,12 @@
; [] fyoucon's segfaults with malloc on win10
; [] handling cursor in non-client part of window so it doesn't spaz
; [] fill screen right away
; [] how to get fast repaint (do I really need double buffering?)
; [] history breaks when heavily used (disk swaping?)
; [] history breaks when heavily used? (disk swaping?)
;
; [] minimize and reopen problem (reported by two users now, still not reproduced here)
; [] minimize and reopen problem (still not reproduced here)
;
; FANCY PANTS IDEAS
; FANCY-PANTS IDEAS
; [] pass messages to 'jobs' to try to avoid cancelling them
; if the job still thinks it should be cancelled it will say so
; but otherwise the job can try to incorporate the new info
@ -225,11 +224,11 @@
; [X] position in file to open
; [X] invoking special tools
; [X] transition Win32 layer to using system_shared stuff
; [X] event driven file synchronization
; [] user settings file
; [] system fonts
; [] file drag and drop
; [] low latency stuff
; [] event driven file synchronization
; [] actually write the port
; [X] 4coder code compiling
; [X] opengl window up
@ -240,12 +239,9 @@
; [X] clipboard (TY:insofaras)
; [X] background threads (TY:insofaras)
; [X] cli stuff (TY:insofaras)
; [X] event diven file synchronization (TY:insofaras)
; [] system fonts
; [] file drag and drop
; [] low latency stuff
; [] allow for multiple clipboards
; [] event diven file synchronization
;
;

View File

@ -24,7 +24,6 @@
#define FCPP_STRING_IMPLEMENTATION
#include "4coder_string.h"
#include "4ed_mem.cpp"
#include "4ed_math.cpp"
#include "4ed_system.h"
@ -286,7 +285,7 @@ LinuxGetMemory_(i32 size, i32 line_number, char *file_name){
result = mmap(0, size + sizeof(Sys_Bubble), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Sys_Bubble* bubble = (Sys_Bubble*)result;
bubble->flags = MEM_BUBBLE_SYS_DEBUG;
bubble->flags = 0;
bubble->line_number = line_number;
bubble->file_name = file_name;
bubble->size = size;
@ -316,7 +315,6 @@ LinuxFreeMemory(void *block){
if (block){
#if FRED_INTERNAL
Sys_Bubble *bubble = ((Sys_Bubble*)block) - 1;
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_SYS_DEBUG);
size_t size = bubble->size + sizeof(Sys_Bubble);
@ -2453,7 +2451,7 @@ main(int argc, char **argv)
#if FRED_INTERNAL
linuxvars.internal_bubble.next = &linuxvars.internal_bubble;
linuxvars.internal_bubble.prev = &linuxvars.internal_bubble;
linuxvars.internal_bubble.flags = MEM_BUBBLE_SYS_DEBUG;
linuxvars.internal_bubble.flags = 0;
pthread_mutex_init(&linuxvars.DEBUG_sysmem_lock, 0);
#endif

View File

@ -242,6 +242,9 @@ gcc_style_verify(String line, int colon_pos){
else if (match_part(line_part, ": warning")){
result = true;
}
else if (match_part(line_part, ": fatal")){
result = true;
}
return(result);
}

View File

@ -16,7 +16,6 @@
#define FSTRING_IMPLEMENTATION
#include "4coder_string.h"
#include "4ed_mem.cpp"
#include "4ed_math.cpp"
#include "4ed_system.h"
@ -245,7 +244,7 @@ Sys_Get_Memory_Sig(system_get_memory_){
#if FRED_INTERNAL
ptr = VirtualAlloc(0, size + sizeof(Sys_Bubble), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
Sys_Bubble *bubble = (Sys_Bubble*)ptr;
bubble->flags = MEM_BUBBLE_SYS_DEBUG;
bubble->flags = 0;
bubble->line_number = line_number;
bubble->file_name = file_name;
bubble->size = size;
@ -264,7 +263,6 @@ Sys_Free_Memory_Sig(system_free_memory){
if (block){
#if FRED_INTERNAL
Sys_Bubble *bubble = ((Sys_Bubble*)block) - 1;
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_SYS_DEBUG);
EnterCriticalSection(&win32vars.DEBUG_sysmem_lock);
remove_bubble(bubble);
LeaveCriticalSection(&win32vars.DEBUG_sysmem_lock);
@ -1698,7 +1696,7 @@ WinMain(HINSTANCE hInstance,
#if FRED_INTERNAL
win32vars.internal_bubble.next = &win32vars.internal_bubble;
win32vars.internal_bubble.prev = &win32vars.internal_bubble;
win32vars.internal_bubble.flags = MEM_BUBBLE_SYS_DEBUG;
win32vars.internal_bubble.flags = 0;
InitializeCriticalSection(&win32vars.DEBUG_sysmem_lock);
#endif