From add72934e0daf475139ca0e6b3899362568f612b Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Tue, 12 Jul 2016 14:20:06 -0400 Subject: [PATCH] search all, and jump to location with return appears to be working --- 4coder_API.html | 215 +++-- 4coder_custom_api.h | 8 + 4coder_default_bindings.cpp | 34 +- ...uilding.cpp => 4coder_default_building.cpp | 144 +-- 4coder_default_include.cpp | 161 +++- 4coder_helper.h | 41 +- 4coder_search.cpp | 891 +++++++++--------- 4coder_types.h | 57 +- 4ed.cpp | 232 ----- 4ed_api_implementation.cpp | 106 ++- 4ed_file_view.cpp | 224 +---- buffer/4coder_buffer_abstract.cpp | 52 +- power/4coder_experiments.cpp | 7 +- 13 files changed, 1118 insertions(+), 1054 deletions(-) rename power/4coder_default_building.cpp => 4coder_default_building.cpp (81%) diff --git a/4coder_API.html b/4coder_API.html index 69e0b799..91144fb6 100644 --- a/4coder_API.html +++ b/4coder_API.html @@ -45,6 +45,7 @@ Coming Soon
  • buffer_boundary_seek
  • buffer_read_range
  • buffer_replace_range
  • +
  • buffer_compute_cursor
  • buffer_batch_edit
  • buffer_set_setting
  • buffer_auto_indent
  • @@ -62,6 +63,7 @@ Coming Soon
  • view_set_split_proportion
  • view_compute_cursor
  • view_set_cursor
  • +
  • view_set_scroll
  • view_set_mark
  • view_set_highlight
  • view_set_buffer
  • @@ -123,6 +125,7 @@ Coming Soon
  • Buffer_Identifier
  • GUI_Scroll_Vars
  • Full_Cursor
  • +
  • Partial_Cursor
  • Buffer_Seek
  • Buffer_Edit
  • Buffer_Summary
  • @@ -258,7 +261,7 @@ first len character of the clipboard contents. The output string is not null te
    Return
    This call returns the summary of the first buffer in a buffer loop.
    Description
    This call begins a loop across all the buffers. If the buffer returned does not exist, the loop is finished. -Buffers should not be killed durring a buffer loop.
    See Also
    Access_Flag
    get_buffer_next

    +Buffers should not be killed durring a buffer loop.
    See Also
    Buffer_Summary
    Access_Flag
    get_buffer_next

    §3.3.8: get_buffer_next

    void app->get_buffer_next( @@ -276,7 +279,7 @@ Buffers should not be killed durring a buffer loop.
    See Also
    Access_Flag
    get_buffer_first

    +Buffers should not be killed or created durring a buffer loop.
    See Also
    Buffer_Summary
    Access_Flag
    get_buffer_first

    §3.3.9: get_buffer

    Buffer_Summary app->get_buffer( @@ -290,7 +293,7 @@ Buffers should not be killed or created durring a buffer loop.
    access
    The access parameter determines what levels of protection this call can access.
    -
    Return
    This call returns a summary that describes the indicated buffer if it exists and is accessible.
    See Also
    Access_Flag
    Buffer_ID

    +
    Return
    This call returns a summary that describes the indicated buffer if it exists and is accessible.
    See Also
    Buffer_Summary
    Access_Flag
    Buffer_ID

    §3.3.10: get_buffer_by_name

    Buffer_Summary app->get_buffer_by_name( @@ -308,7 +311,7 @@ Buffers should not be killed or created durring a buffer loop.
    access
    The access parameter determines what levels of protection this call can access.
    -
    Return
    This call returns a summary that describes the indicated buffer if it exists and is accessible.
    See Also
    Access_Flag

    +
    Return
    This call returns a summary that describes the indicated buffer if it exists and is accessible.
    See Also
    Buffer_Summary
    Access_Flag

    §3.3.11: buffer_boundary_seek

    int32_t app->buffer_boundary_seek( @@ -392,8 +395,28 @@ 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.
    See Also
    4coder_Buffer_Positioning_System

    +
    +

    §3.3.14: buffer_compute_cursor

    +
    bool32 app->buffer_compute_cursor( +
    Application_Links *app,
    Buffer_Summary *buffer,
    Buffer_Seek seek,
    Partial_Cursor *cursor_out
    ) +
    +
    Parameters
    +
    buffer
    +
    The buffer parameter specifies the buffer on which to run the cursor computation.
    +
    +
    +
    seek
    +
    The seek parameter specifies the target position for the seek.
    +
    +
    +
    cursor_out
    +
    On success this struct is filled with the result of the seek.
    +
    +
    Return
    This call returns non-zero on success.
    Description
    Computes a Partial_Cursor for the given seek position with no side effects. +The seek position must be one of the types supported by Partial_Cursor. Those +types are absolute position and line,column position.
    See Also
    Buffer_Seek
    Partial_Cursor

    -

    §3.3.14: buffer_batch_edit

    +

    §3.3.15: buffer_batch_edit

    bool32 app->buffer_batch_edit(
    Application_Links *app,
    Buffer_Summary *buffer,
    char *str,
    int32_t str_len,
    Buffer_Edit *edits,
    int32_t edit_count,
    Buffer_Batch_Edit_Type type
    )
    @@ -419,7 +442,7 @@ range is not within the bounds of the buffer.
    Return
    This call returns non-zero if the batch edit succeeds.
    Description
    TODO
    See Also
    Buffer_Edit
    Buffer_Batch_Edit_Type

    -

    §3.3.15: buffer_set_setting

    +

    §3.3.16: buffer_set_setting

    bool32 app->buffer_set_setting(
    Application_Links *app,
    Buffer_Summary *buffer,
    Buffer_Setting_ID setting,
    int32_t value
    )
    @@ -437,7 +460,7 @@ range is not within the bounds of the buffer.
    See Also
    Buffer_Setting_ID

    -

    §3.3.16: buffer_auto_indent

    +

    §3.3.17: buffer_auto_indent

    bool32 app->buffer_auto_indent(
    Application_Links *app,
    Buffer_Summary *buffer,
    int32_t start,
    int32_t end,
    int32_t tab_width,
    Auto_Indent_Flag flags
    )
    @@ -466,7 +489,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.
    See Also
    Auto_Indent_Flag
    4coder_Buffer_Positioning_System

    -

    §3.3.17: create_buffer

    +

    §3.3.18: create_buffer

    Buffer_Summary app->create_buffer(
    Application_Links *app,
    char *filename,
    int32_t filename_len,
    Buffer_Create_Flag flags
    )
    @@ -486,9 +509,9 @@ completed this function will fail.
    See Also
    Buffer_Create_Flag

    +the filename does not correspond to a file on disk the buffer is created empty.
    See Also
    Buffer_Summary
    Buffer_Create_Flag

    -

    §3.3.18: save_buffer

    +

    §3.3.19: save_buffer

    bool32 app->save_buffer(
    Application_Links *app,
    Buffer_Summary *buffer,
    char *filename,
    int32_t filename_len,
    uint32_t flags
    )
    @@ -510,7 +533,7 @@ the filename does not correspond to a file on disk the buffer is created empty.<
    Return
    This call returns non-zero on success.

    -

    §3.3.19: kill_buffer

    +

    §3.3.20: kill_buffer

    bool32 app->kill_buffer(
    Application_Links *app,
    Buffer_Identifier buffer,
    View_ID view_id,
    Buffer_Kill_Flag flags
    )
    @@ -530,7 +553,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.
    See Also
    Buffer_Kill_Flag
    Buffer_Identifier

    -

    §3.3.20: get_view_first

    +

    §3.3.21: get_view_first

    View_Summary app->get_view_first(
    Application_Links *app,
    Access_Flag access
    )
    @@ -543,7 +566,7 @@ If the view is not open the kill fails.
    See Also
    Access_Flag
    get_view_next

    -

    §3.3.21: get_view_next

    +

    §3.3.22: get_view_next

    void app->get_view_next(
    Application_Links *app,
    View_Summary *view,
    Access_Flag access
    )
    @@ -560,7 +583,7 @@ Views should not be closed or opened durring a view loop.
    See Also
    Access_Flag
    get_view_first

    -

    §3.3.22: get_view

    +

    §3.3.23: get_view

    View_Summary app->get_view(
    Application_Links *app,
    View_ID view_id,
    Access_Flag access
    )
    @@ -574,7 +597,7 @@ Views should not be closed or opened durring a view loop.
    Return
    This call returns a summary that describes the indicated view if it is open and accessible.
    See Also
    Access_Flag

    -

    §3.3.23: get_active_view

    +

    §3.3.24: get_active_view

    View_Summary app->get_active_view(
    Application_Links *app,
    Access_Flag access
    )
    @@ -584,7 +607,7 @@ Views should not be closed or opened durring a view loop.
    Return
    This call returns a summary that describes the active view.
    See Also
    set_active_view
    Access_Flag

    -

    §3.3.24: open_view

    +

    §3.3.25: open_view

    View_Summary app->open_view(
    Application_Links *app,
    View_Summary *view_location,
    View_Split_Position position
    )
    @@ -600,7 +623,7 @@ Views should not be closed or opened durring a view loop.
    Description
    4coder is built with a limit of 16 views. If 16 views are already open when this is called the call will fail.
    See Also
    View_Split_Position

    -

    §3.3.25: close_view

    +

    §3.3.26: close_view

    bool32 app->close_view(
    Application_Links *app,
    View_Summary *view
    )
    @@ -613,7 +636,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.

    -

    §3.3.26: set_active_view

    +

    §3.3.27: set_active_view

    bool32 app->set_active_view(
    Application_Links *app,
    View_Summary *view
    )
    @@ -625,7 +648,7 @@ If the given view is the last open view in the system, the call will fail.
    active view, and takes subsequent commands and is returned from get_active_view.
    See Also
    get_active_view

    -

    §3.3.27: view_set_setting

    +

    §3.3.28: view_set_setting

    bool32 app->view_set_setting(
    Application_Links *app,
    View_Summary *view,
    View_Setting_ID setting,
    int32_t value
    )
    @@ -643,7 +666,7 @@ from get_active_view.
    Return
    This call returns non-zero on success.
    See Also
    View_Setting_ID

    -

    §3.3.28: view_set_split_proportion

    +

    §3.3.29: view_set_split_proportion

    bool32 app->view_set_split_proportion(
    Application_Links *app,
    View_Summary *view,
    float t
    )
    @@ -657,7 +680,7 @@ from get_active_view.
    Return
    This call returns non-zero on success.

    -

    §3.3.29: view_compute_cursor

    +

    §3.3.30: view_compute_cursor

    bool32 app->view_compute_cursor(
    Application_Links *app,
    View_Summary *view,
    Buffer_Seek seek,
    Full_Cursor *cursor_out
    )
    @@ -675,7 +698,7 @@ from get_active_view.
    Return
    This call returns non-zero on success.
    Description
    Computes a Full_Cursor for the given seek position with no side effects.
    See Also
    Buffer_Seek
    Full_Cursor

    -

    §3.3.30: view_set_cursor

    +

    §3.3.31: view_set_cursor

    bool32 app->view_set_cursor(
    Application_Links *app,
    View_Summary *view,
    Buffer_Seek seek,
    bool32 set_preferred_x
    )
    @@ -694,8 +717,14 @@ from get_active_view.
    Return
    This call returns non-zero on success.
    Description
    This call sets the the view's cursor position. set_preferred_x should usually be true unless the change in cursor position is is a vertical motion that tries to keep the cursor in the same column or x position.
    See Also
    Buffer_Seek

    +
    +

    §3.3.32: view_set_scroll

    +
    bool32 app->view_set_scroll( +
    Application_Links *app,
    View_Summary *view,
    GUI_Scroll_Vars scroll
    ) +
    +
    Description
    TODO
    See Also
    GUI_Scroll_Vars

    -

    §3.3.31: view_set_mark

    +

    §3.3.33: view_set_mark

    bool32 app->view_set_mark(
    Application_Links *app,
    View_Summary *view,
    Buffer_Seek seek
    )
    @@ -709,7 +738,7 @@ cursor in the same column or x position.
    Return
    This call returns non-zero on success.
    Description
    This call sets the the view's mark position.
    See Also
    Buffer_Seek

    -

    §3.3.32: view_set_highlight

    +

    §3.3.34: view_set_highlight

    bool32 app->view_set_highlight(
    Application_Links *app,
    View_Summary *view,
    int32_t start,
    int32_t end,
    bool32 turn_on
    )
    @@ -734,7 +763,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.

    -

    §3.3.33: view_set_buffer

    +

    §3.3.35: view_set_buffer

    bool32 app->view_set_buffer(
    Application_Links *app,
    View_Summary *view,
    Buffer_ID buffer_id,
    Set_Buffer_Flag flags
    )
    @@ -753,7 +782,7 @@ the turn_on set to false, will switch back to showing the cursor.

    Return
    This call returns non-zero on success.
    Description
    On success view_set_buffer sets the specified view's current buffer and cancels and dialogue shown in the view and displays the file.
    See Also
    Set_Buffer_Flag

    -

    §3.3.34: view_post_fade

    +

    §3.3.36: view_post_fade

    bool32 app->view_post_fade(
    Application_Links *app,
    View_Summary *view,
    float seconds,
    int32_t start,
    int32_t end,
    int_color color
    )
    @@ -779,7 +808,7 @@ cancels and dialogue shown in the view and displays the file.
    Return
    This call returns non-zero on success.
    See Also
    int_color

    -

    §3.3.35: get_user_input

    +

    §3.3.37: get_user_input

    User_Input app->get_user_input(
    Application_Links *app,
    Input_Type_Flag get_type,
    Input_Type_Flag abort_type
    )
    @@ -797,19 +826,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.
    See Also
    Input_Type_Flag
    User_Input

    -

    §3.3.36: get_command_input

    +

    §3.3.38: get_command_input

    User_Input app->get_command_input(
    Application_Links *app
    )
    Return
    This call returns the input that triggered the currently executing command.
    See Also
    User_Input

    -

    §3.3.37: get_mouse_state

    +

    §3.3.39: get_mouse_state

    Mouse_State app->get_mouse_state(
    Application_Links *app
    )
    Return
    This call returns the current mouse state as of the beginning of the frame.
    See Also
    Mouse_State

    -

    §3.3.38: start_query_bar

    +

    §3.3.40: start_query_bar

    bool32 app->start_query_bar(
    Application_Links *app,
    Query_Bar *bar,
    uint32_t flags
    )
    @@ -829,7 +858,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.

    -

    §3.3.39: end_query_bar

    +

    §3.3.41: end_query_bar

    void app->end_query_bar(
    Application_Links *app,
    Query_Bar *bar,
    uint32_t flags
    )
    @@ -843,7 +872,7 @@ only use for this call is in an interactive command that makes calls to get_user
    Description
    Stops showing the particular query bar specified by the bar parameter.

    Description
    This call posts a string to the *messages* buffer.

    -

    §3.3.41: change_theme

    +

    §3.3.43: change_theme

    void app->change_theme(
    Application_Links *app,
    char *name,
    int32_t len
    )
    @@ -871,7 +900,7 @@ only use for this call is in an interactive command that makes calls to get_user
    Description
    This call changes 4coder's theme to one of the built in themes.

    -

    §3.3.42: change_font

    +

    §3.3.44: change_font

    void app->change_font(
    Application_Links *app,
    char *name,
    int32_t len
    )
    @@ -885,7 +914,7 @@ only use for this call is in an interactive command that makes calls to get_user
    Description
    This call changes 4coder's font to one of the built in fonts.

    -

    §3.3.43: set_theme_colors

    +

    §3.3.45: set_theme_colors

    void app->set_theme_colors(
    Application_Links *app,
    Theme_Color *colors,
    int32_t count
    )
    @@ -901,7 +930,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.

    -

    §3.3.44: get_theme_colors

    +

    §3.3.46: get_theme_colors

    void app->get_theme_colors(
    Application_Links *app,
    Theme_Color *colors,
    int32_t count
    )
    @@ -917,7 +946,7 @@ no change is made to the color pallet.

    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.
    -

    §3.3.45: directory_get_hot

    +

    §3.3.47: directory_get_hot

    int32_t app->directory_get_hot(
    Application_Links *app,
    char *out,
    int32_t capacity
    )
    @@ -935,7 +964,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.

    -

    §3.3.46: get_file_list

    +

    §3.3.48: get_file_list

    File_List app->get_file_list(
    Application_Links *app,
    char *dir,
    int32_t len
    )
    @@ -951,7 +980,7 @@ directories controlled on the custom side.

    the specified directory. The File_List returned should be passed to free_file_list when it is no longer in use.
    -

    §3.3.47: free_file_list

    +

    §3.3.49: free_file_list

    void app->free_file_list(
    Application_Links *app,
    File_List list
    )
    @@ -961,25 +990,25 @@ when it is no longer in use.

    Description
    After this call the file list passed in should not be read or written to.

    -

    §3.3.48: memory_allocate

    +

    §3.3.50: memory_allocate

    void* app->memory_allocate(
    Application_Links *app,
    int32_t size
    )
    Description
    TODO

    -

    §3.3.49: memory_set_protection

    +

    §3.3.51: memory_set_protection

    bool32 app->memory_set_protection(
    Application_Links *app,
    void *ptr,
    int32_t size,
    Memory_Protect_Flags flags
    )
    Description
    TODO

    -

    §3.3.50: memory_free

    +

    §3.3.52: memory_free

    void app->memory_free(
    Application_Links *app,
    void *mem,
    int32_t size
    )
    Description
    TODO

    -

    §3.3.51: file_exists

    +

    §3.3.53: file_exists

    bool32 app->file_exists(
    Application_Links *app,
    char *filename,
    int len
    )
    @@ -993,7 +1022,7 @@ when it is no longer in use.

    Return
    This call returns non-zero if and only if the file exists.

    -

    §3.3.52: directory_cd

    +

    §3.3.54: directory_cd

    bool32 app->directory_cd(
    Application_Links *app,
    char *dir,
    int *len,
    int capacity,
    char *rel_path,
    int rel_len
    )
    @@ -1026,7 +1055,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.

    -

    §3.3.53: get_4ed_path

    +

    §3.3.55: get_4ed_path

    bool32 app->get_4ed_path(
    Application_Links *app,
    char *out,
    int32_t capacity
    )
    @@ -1040,7 +1069,7 @@ folders.

    Return
    This call returns non-zero on success.

    -

    §3.3.54: show_mouse_cursor

    +

    §3.3.56: show_mouse_cursor

    void app->show_mouse_cursor(
    Application_Links *app,
    Mouse_Cursor_Show_Type show
    )
    @@ -1111,18 +1140,6 @@ the range [1,16].

    cmdid_null is set aside to always be zero and is not associated with any command.
    -
    cmdid_center_view
    -
    cmdid_center_view centers the view vertically on the cursor.
    -
    -
    -
    cmdid_left_adjust_view
    -
    cmdid_left_adjust_view adjusts the view to be just left of the cursor's position.
    -
    -
    -
    cmdid_word_complete
    -
    cmdid_word_complete begins or continues cycling through completions for a partial word.
    -
    -
    cmdid_undo
    cmdid_undo performs a standard undo behavior.
    @@ -1147,14 +1164,6 @@ the range [1,16].
    cmdid_interactive_open begins an interactive dialogue to open a file into a buffer.
    -
    cmdid_reopen
    -
    cmdid_reopen reloads the active buffer's associated file and discards the old buffer contents for the reloaded file.
    -
    -
    -
    cmdid_save
    -
    cmdid_save saves the buffer's contents into the associated file.
    -
    -
    cmdid_save_as
    cmdid_save_as does not currently work and is likely to be removed rather that fixed.
    @@ -1167,6 +1176,14 @@ the range [1,16].
    cmdid_interactive_kill_buffer begins an interactive dialogue to choose an open buffer to kill.
    +
    cmdid_reopen
    +
    cmdid_reopen reloads the active buffer's associated file and discards the old buffer contents for the reloaded file.
    +
    +
    +
    cmdid_save
    +
    cmdid_save saves the buffer's contents into the associated file.
    +
    +
    cmdid_kill_buffer
    cmdid_kill_buffer tries to kill the active buffer.
    @@ -1265,9 +1282,20 @@ the range [1,16].
    BufferSetting_Eol
    -
    The BufferSetting_Eol setting spcifies how line ends should be saved to the backing file. +
    The BufferSetting_Eol setting specifies how line ends should be saved to the backing file. A 1 indicates dos endings "\r\n" and a 0 indicates nix endings "\n".
    +
    +
    BufferSetting_Unimportant
    +
    The BufferSetting_Unimportant setting marks a buffer so that it's dirty state will be completely + ignored. This means the "dirty" star is hidden and the buffer can be closed without presenting an + "are you sure" dialogue screen.
    +
    +
    +
    BufferSetting_ReadOnly
    +
    The BufferSetting_ReadOnly setting marks a buffer so that it can only be returned from buffer + access calls that include an AccessProtected flag.
    +

    §3.4.12: View_Setting_ID

    @@ -1393,7 +1421,7 @@ Flags can be combined with bit or to specify a state with multiple modifiers.
    BufferCreate_AlwaysNew = 0x2
    -
    When BufferCreate_AlwaysNew is et it indicates the buffer should be +
    When BufferCreate_AlwaysNew is set it indicates the buffer should be cleared to empty even if it's associated file already has content.

    @@ -1832,7 +1860,8 @@ float wrapped_y;
    };
    Description
    Full_Cursor describes the position of a cursor in every buffer -coordinate system supported by 4coder.
    Fields
    +coordinate system supported by 4coder. This cursor type requires that +the buffer is associated with a view to give the x/y values meaning.
    Fields
    pos
    This field contains the cursor's position in absolute positioning.
    @@ -1861,8 +1890,34 @@ coordinate system supported by 4coder.
    This field contains the y position measured with wrapped lines.
    See Also
    4coder_Buffer_Positioning_System

    +
    +

    §3.4.35: Partial_Cursor

    +
    struct Partial_Cursor {
    +
    +int32_t pos;
    +int32_t line;
    +int32_t character;
    +
    +};
    +
    +
    Description
    Partial_Cursor describes the position of a cursor in all of +the coordinate systems that a invariant to the View. In other words +the coordinate systems available here can be used on a buffer that is +not currently associated with a View.
    Fields
    +
    pos
    +
    This field contains the cursor's position in absolute positioning.
    +
    +
    +
    line
    +
    This field contains the number of the line where the cursor is located. This field is one based.
    +
    +
    +
    character
    +
    This field contains the number of the column where the cursor is located. This field is one based.
    +
    +
    See Also
    4coder_Buffer_Positioning_System

    -

    §3.4.35: Buffer_Seek

    +

    §3.4.36: Buffer_Seek

    struct Buffer_Seek {
    Buffer_Seek_Type type;
    @@ -1927,7 +1982,7 @@ for concisely creating Buffer_Seek structs. They can be found in 4coder_buffer_
    See Also
    Buffer_Seek_Type
    4coder_Buffer_Positioning_System

    -

    §3.4.36: Buffer_Edit

    +

    §3.4.37: Buffer_Edit

    struct Buffer_Edit {
    int32_t str_start;
    @@ -1957,7 +2012,7 @@ will be replaced into the buffer.
    -

    §3.4.37: Buffer_Summary

    +

    §3.4.38: Buffer_Summary

    struct Buffer_Summary {
    bool32 exists;
    @@ -2032,7 +2087,7 @@ bool32 unwrapped_lines;
    See Also

    -

    §3.4.38: View_Summary

    +

    §3.4.39: View_Summary

    struct View_Summary {
    bool32 exists;
    @@ -2094,15 +2149,15 @@ GUI_Scroll_Vars scroll_vars;
    file_region
    -
    This feature is not fully implemented yet.
    +
    If this is not a null summary, this describes the screen position in which this view's buffer is displayed.
    scroll_vars
    -
    This feature is not fully implemented yet.
    +
    If this is not a null summary, this describes the scrolling position inside the view.
    -
    See Also

    +
    See Also

    -

    §3.4.39: User_Input

    +

    §3.4.40: User_Input

    struct User_Input {
    User_Input_Type_ID type;
    @@ -2139,7 +2194,7 @@ Generic_Command command;
    See Also

    -

    §3.4.40: Query_Bar

    +

    §3.4.41: Query_Bar

    struct Query_Bar {
    String prompt;
    @@ -2158,7 +2213,7 @@ that will be displayed as a drop down bar durring an interactive command.
    <

    -

    §3.4.41: Event_Message

    +

    §3.4.42: Event_Message

    struct Event_Message {
    int type;
    @@ -2171,7 +2226,7 @@ int type;

    -

    §3.4.42: Theme_Color

    +

    §3.4.43: Theme_Color

    struct Theme_Color {
    Style_Tag tag;
    diff --git a/4coder_custom_api.h b/4coder_custom_api.h index 81a12a9c..07ac0fe0 100644 --- a/4coder_custom_api.h +++ b/4coder_custom_api.h @@ -11,6 +11,7 @@ #define BUFFER_BOUNDARY_SEEK_SIG(n) int32_t n(Application_Links *app, Buffer_Summary *buffer, int32_t start_pos, bool32 seek_forward, Seek_Boundary_Flag flags) #define BUFFER_READ_RANGE_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, char *out) #define BUFFER_REPLACE_RANGE_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, char *str, int32_t len) +#define BUFFER_COMPUTE_CURSOR_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Buffer_Seek seek, Partial_Cursor *cursor_out) #define BUFFER_BATCH_EDIT_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type) #define BUFFER_SET_SETTING_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t value) #define BUFFER_AUTO_INDENT_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, int32_t tab_width, Auto_Indent_Flag flags) @@ -28,6 +29,7 @@ #define VIEW_SET_SPLIT_PROPORTION_SIG(n) bool32 n(Application_Links *app, View_Summary *view, float t) #define VIEW_COMPUTE_CURSOR_SIG(n) bool32 n(Application_Links *app, View_Summary *view, Buffer_Seek seek, Full_Cursor *cursor_out) #define VIEW_SET_CURSOR_SIG(n) bool32 n(Application_Links *app, View_Summary *view, Buffer_Seek seek, bool32 set_preferred_x) +#define VIEW_SET_SCROLL_SIG(n) bool32 n(Application_Links *app, View_Summary *view, GUI_Scroll_Vars scroll) #define VIEW_SET_MARK_SIG(n) bool32 n(Application_Links *app, View_Summary *view, Buffer_Seek seek) #define VIEW_SET_HIGHLIGHT_SIG(n) bool32 n(Application_Links *app, View_Summary *view, int32_t start, int32_t end, bool32 turn_on) #define VIEW_SET_BUFFER_SIG(n) bool32 n(Application_Links *app, View_Summary *view, Buffer_ID buffer_id, Set_Buffer_Flag flags) @@ -66,6 +68,7 @@ extern "C"{ typedef BUFFER_BOUNDARY_SEEK_SIG(Buffer_Boundary_Seek_Function); typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function); typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function); + typedef BUFFER_COMPUTE_CURSOR_SIG(Buffer_Compute_Cursor_Function); typedef BUFFER_BATCH_EDIT_SIG(Buffer_Batch_Edit_Function); typedef BUFFER_SET_SETTING_SIG(Buffer_Set_Setting_Function); typedef BUFFER_AUTO_INDENT_SIG(Buffer_Auto_Indent_Function); @@ -83,6 +86,7 @@ extern "C"{ typedef VIEW_SET_SPLIT_PROPORTION_SIG(View_Set_Split_Proportion_Function); typedef VIEW_COMPUTE_CURSOR_SIG(View_Compute_Cursor_Function); typedef VIEW_SET_CURSOR_SIG(View_Set_Cursor_Function); + typedef VIEW_SET_SCROLL_SIG(View_Set_Scroll_Function); typedef VIEW_SET_MARK_SIG(View_Set_Mark_Function); typedef VIEW_SET_HIGHLIGHT_SIG(View_Set_Highlight_Function); typedef VIEW_SET_BUFFER_SIG(View_Set_Buffer_Function); @@ -124,6 +128,7 @@ struct Application_Links{ Buffer_Boundary_Seek_Function *buffer_boundary_seek; Buffer_Read_Range_Function *buffer_read_range; Buffer_Replace_Range_Function *buffer_replace_range; + Buffer_Compute_Cursor_Function *buffer_compute_cursor; Buffer_Batch_Edit_Function *buffer_batch_edit; Buffer_Set_Setting_Function *buffer_set_setting; Buffer_Auto_Indent_Function *buffer_auto_indent; @@ -141,6 +146,7 @@ struct Application_Links{ View_Set_Split_Proportion_Function *view_set_split_proportion; View_Compute_Cursor_Function *view_compute_cursor; View_Set_Cursor_Function *view_set_cursor; + View_Set_Scroll_Function *view_set_scroll; View_Set_Mark_Function *view_set_mark; View_Set_Highlight_Function *view_set_highlight; View_Set_Buffer_Function *view_set_buffer; @@ -184,6 +190,7 @@ app_links->get_buffer_by_name = Get_Buffer_By_Name;\ app_links->buffer_boundary_seek = Buffer_Boundary_Seek;\ app_links->buffer_read_range = Buffer_Read_Range;\ app_links->buffer_replace_range = Buffer_Replace_Range;\ +app_links->buffer_compute_cursor = Buffer_Compute_Cursor;\ app_links->buffer_batch_edit = Buffer_Batch_Edit;\ app_links->buffer_set_setting = Buffer_Set_Setting;\ app_links->buffer_auto_indent = Buffer_Auto_Indent;\ @@ -201,6 +208,7 @@ app_links->view_set_setting = View_Set_Setting;\ app_links->view_set_split_proportion = View_Set_Split_Proportion;\ app_links->view_compute_cursor = View_Compute_Cursor;\ app_links->view_set_cursor = View_Set_Cursor;\ +app_links->view_set_scroll = View_Set_Scroll;\ app_links->view_set_mark = View_Set_Mark;\ app_links->view_set_highlight = View_Set_Highlight;\ app_links->view_set_buffer = View_Set_Buffer;\ diff --git a/4coder_default_bindings.cpp b/4coder_default_bindings.cpp index 566f8bc0..f7f80774 100644 --- a/4coder_default_bindings.cpp +++ b/4coder_default_bindings.cpp @@ -5,6 +5,7 @@ #define FCODER_DEFAULT_BINDINGS #include "4coder_default_include.cpp" +#include "4coder_default_building.cpp" // NOTE(allen|a3.3): All of your custom ids should be enumerated // as shown here, they may start at 0, and you can only have @@ -153,6 +154,19 @@ HOOK_SIG(my_start){ return(0); } +CUSTOM_COMMAND_SIG(newline_or_goto_position){ + View_Summary view = app->get_active_view(app, AccessProtected); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, AccessProtected); + + if (buffer.lock_flags & AccessProtected){ + exec_command(app, goto_postion_at_cursor); + } + else{ + exec_command(app, write_character); + } +} + +// TODO(allen): Eliminate this hook if you can. OPEN_FILE_HOOK_SIG(my_file_settings){ // NOTE(allen|a4.0.8): The app->get_parameter_buffer was eliminated // and instead the buffer is passed as an explicit parameter through @@ -183,7 +197,6 @@ OPEN_FILE_HOOK_SIG(my_file_settings){ app->buffer_set_setting(app, &buffer, BufferSetting_WrapLine, wrap_lines); app->buffer_set_setting(app, &buffer, BufferSetting_MapID, (treat_as_code)?((int)my_code_map):((int)mapid_file)); - // TODO(allen): Eliminate this hook if you can. // no meaning for return return(0); } @@ -192,6 +205,8 @@ OPEN_FILE_HOOK_SIG(my_file_settings){ // If this hook is not implemented a default behavior of calling the // command is used. It is important to note that paste_next does not // work without this hook. +// NOTE(allen|a4.0.10): As of this version the word_complete command also +// relies on this particular command caller hook. COMMAND_CALLER_HOOK(my_command_caller){ View_Summary view = app->get_active_view(app, AccessAll); @@ -261,6 +276,11 @@ default_keys(Bind_Helper *context){ bind(context, 'o', MDFR_ALT, open_in_other); bind(context, 'w', MDFR_CTRL, save_as); + bind(context, '.', MDFR_ALT, change_to_build_panel); + bind(context, ',', MDFR_ALT, close_build_panel); + bind(context, 'n', MDFR_ALT, goto_next_error); + bind(context, 'N', MDFR_ALT, goto_prev_error); + bind(context, 'M', MDFR_ALT, goto_first_error); bind(context, 'm', MDFR_ALT, build_search); bind(context, 'x', MDFR_ALT, execute_arbitrary_command); bind(context, 'z', MDFR_ALT, execute_any_cli); @@ -287,6 +307,7 @@ default_keys(Bind_Helper *context){ // and write character writes whichever character corresponds // to the key that triggered the command. bind(context, '\n', MDFR_NONE, write_and_auto_tab); + bind(context, '\n', MDFR_SHIFT, write_and_auto_tab); bind(context, '}', MDFR_NONE, write_and_auto_tab); bind(context, ')', MDFR_NONE, write_and_auto_tab); bind(context, ']', MDFR_NONE, write_and_auto_tab); @@ -297,7 +318,6 @@ default_keys(Bind_Helper *context){ bind(context, '\t', MDFR_CTRL, auto_tab_range); bind(context, '\t', MDFR_SHIFT, auto_tab_line_at_cursor); - bind(context, '=', MDFR_CTRL, write_increment); bind(context, 't', MDFR_ALT, write_allen_todo); bind(context, 'y', MDFR_ALT, write_allen_note); bind(context, 'r', MDFR_ALT, write_allen_doc); @@ -353,9 +373,10 @@ default_keys(Bind_Helper *context){ bind(context, 'a', MDFR_CTRL, replace_in_range); bind(context, 'c', MDFR_CTRL, copy); bind(context, 'd', MDFR_CTRL, delete_range); - bind(context, 'e', MDFR_CTRL, cmdid_center_view); - bind(context, 'E', MDFR_CTRL, cmdid_left_adjust_view); + bind(context, 'e', MDFR_CTRL, center_view); + bind(context, 'E', MDFR_CTRL, left_adjust_view); bind(context, 'f', MDFR_CTRL, search); + bind(context, 'F', MDFR_CTRL, list_all_locations); bind(context, 'g', MDFR_CTRL, goto_line); bind(context, 'h', MDFR_CTRL, cmdid_history_backward); bind(context, 'H', MDFR_CTRL, cmdid_history_forward); @@ -377,13 +398,14 @@ default_keys(Bind_Helper *context){ bind(context, 'y', MDFR_CTRL, cmdid_redo); bind(context, 'z', MDFR_CTRL, cmdid_undo); - + bind(context, '=', MDFR_CTRL, goto_postion_at_cursor); bind(context, '1', MDFR_CTRL, eol_dosify); bind(context, '!', MDFR_CTRL, eol_nixify); bind(context, '?', MDFR_CTRL, toggle_show_whitespace); bind(context, '~', MDFR_CTRL, clean_all_lines); - bind(context, '\n', MDFR_SHIFT, write_and_auto_tab); + bind(context, '\n', MDFR_NONE, newline_or_goto_position); + bind(context, '\n', MDFR_SHIFT, newline_or_goto_position); bind(context, ' ', MDFR_SHIFT, write_character); end_map(context); diff --git a/power/4coder_default_building.cpp b/4coder_default_building.cpp similarity index 81% rename from power/4coder_default_building.cpp rename to 4coder_default_building.cpp index 4f295a53..481b3b42 100644 --- a/power/4coder_default_building.cpp +++ b/4coder_default_building.cpp @@ -185,40 +185,6 @@ CUSTOM_COMMAND_SIG(open_in_other_build){ // Jump to Error // -static int -read_line(Application_Links *app, - View_Summary *view, - int line, - String *str){ - - Full_Cursor begin = {0}; - Full_Cursor end = {0}; - - int success = false; - - if (app->view_compute_cursor(app, view, - seek_line_char(line, 1), &begin)){ - if (app->view_compute_cursor(app, view, - seek_line_char(line, 65536), &end)){ - - Buffer_Summary buffer = app->get_buffer(app, view->buffer_id, AccessAll); - if (begin.line == line){ - if (0 <= begin.pos && begin.pos <= end.pos && end.pos <= buffer.size){ - int size = (end.pos - begin.pos); - if (size <= str->memory_size){ - success = true; - app->buffer_read_range(app, &buffer, begin.pos, end.pos, str->str); - str->size = size; - } - } - } - - } - } - - return(success); -} - struct Jump_Location{ String file; int line; @@ -234,18 +200,9 @@ jump_to_location(Application_Links *app, View_Summary *view, Jump_Location *l){ static int gcc_style_verify(String line, int colon_pos){ int result = false; - - String line_part = substr(line, colon_pos); - if (match_part(line_part, ": error")){ + if (colon_pos < line.size){ result = true; } - else if (match_part(line_part, ": warning")){ - result = true; - } - else if (match_part(line_part, ": fatal")){ - result = true; - } - return(result); } @@ -298,7 +255,8 @@ parse_error(String line, Jump_Location *location, if (line_number.size > 0){ - copy(&location->file, file); + //copy(&location->file, file); + location->file = file; int comma_pos = find(line_number, 0, ','); if (comma_pos < line_number.size){ @@ -327,6 +285,7 @@ parse_error(String line, Jump_Location *location, int colon_pos1 = find(line, 0, ':'); int colon_pos2 = find(line, colon_pos1+1, ':'); int colon_pos3 = find(line, colon_pos2+1, ':'); + if (gcc_style_verify(line, colon_pos3)){ String filename = substr(line, 0, colon_pos1); String line_number = substr(line, colon_pos1+1, colon_pos2 - colon_pos1 - 1); @@ -335,13 +294,30 @@ parse_error(String line, Jump_Location *location, if (filename.size > 0 && line_number.size > 0 && column_number.size > 0){ - copy(&location->file, filename); + //copy(&location->file, filename); + location->file = filename; location->line = str_to_int(line_number); location->column = str_to_int(column_number); *colon_char = colon_pos3; result = true; } } + else{ + int colon_pos1 = find(line, 0, ':'); + int colon_pos2 = find(line, colon_pos1+1, ':'); + + String filename = substr(line, 0, colon_pos1); + String line_number = substr(line, colon_pos1+1, colon_pos2 - colon_pos1 - 1); + + if (filename.size > 0 && line_number.size > 0){ + //copy(&location->file, filename); + location->file = filename; + location->line = str_to_int(line_number); + location->column = 0; + *colon_char = colon_pos2; + result = true; + } + } } return(result); @@ -349,18 +325,19 @@ parse_error(String line, Jump_Location *location, static int next_error(Application_Links *app, - View_Summary *comp_out, int *start_line, - void *memory, int memory_size, - Jump_Location *location, - int direction, - int skip_sub_errors, - int *colon_char){ + Partition *part, + View_Summary *comp_out, int *start_line, + Jump_Location *location, + int direction, + int skip_sub_errors, + int *colon_char){ int result = false; int line = *start_line + direction; - String line_str = make_string(memory, 0, memory_size); + String line_str = {0}; + Buffer_Summary buffer = app->get_buffer(app, comp_out->buffer_id, AccessAll); for (;;){ - if (read_line(app, comp_out, line, &line_str)){ + if (read_line(app, part, &buffer, line, &line_str)){ if (parse_error(line_str, location, skip_sub_errors, colon_char)){ result = true; break; @@ -382,7 +359,27 @@ next_error(Application_Links *app, } static int -goto_error(Application_Links *app, int direction, int skip_sub_errors, Jump_Location *loc){ +goto_error(Application_Links *app, + Partition *part, + View_Summary *view, int line, + Jump_Location *location, + int skip_sub_errors){ + + int result = false; + String line_str = {0}; + Buffer_Summary buffer = app->get_buffer(app, view->buffer_id, AccessAll); + if (read_line(app, part, &buffer, line, &line_str)){ + int colon_char = 0; + if (parse_error(line_str, location, skip_sub_errors, &colon_char)){ + result = true; + } + } + + return(result); +} + +static int +seek_error(Application_Links *app, Partition *part, int direction, int skip_sub_errors, Jump_Location *loc){ int result = false; View_Summary active_view = app->get_active_view(app, AccessAll); @@ -392,12 +389,8 @@ goto_error(Application_Links *app, int direction, int skip_sub_errors, Jump_Loca View_Summary view = get_first_view_with_buffer(app, buffer.buffer_id); int line = view.cursor.line; - int ms = app->memory_size/2; - location.file = make_string(app->memory, 0, ms); - void *m = (char*)app->memory + ms; - int colon_char = 0; - if (next_error(app, &view, &line, m, ms, &location, + if (next_error(app, part, &view, &line, &location, skip_sub_errors, direction, &colon_char)){ jump_to_location(app, &active_view, &location); app->view_set_cursor(app, &view, seek_line_char(line, colon_char+1), true); @@ -435,11 +428,11 @@ skip_this_jump(Prev_Jump prev, Prev_Jump jump){ } CUSTOM_COMMAND_SIG(goto_next_error){ + Temp_Memory temp = begin_temp_memory(&global_part); Jump_Location location = {0}; Prev_Jump jump = {0}; - do{ - if (goto_error(app, true, 1, &location)){ + if (seek_error(app, &global_part, true, 1, &location)){ jump = jump_location_store(app, location); } else{ @@ -447,14 +440,15 @@ CUSTOM_COMMAND_SIG(goto_next_error){ } }while(skip_this_jump(prev_location, jump)); prev_location = jump; + end_temp_memory(temp); } CUSTOM_COMMAND_SIG(goto_prev_error){ + Temp_Memory temp = begin_temp_memory(&global_part); Jump_Location location = {0}; Prev_Jump jump = {0}; - do{ - if (goto_error(app, true, -1, &location)){ + if (seek_error(app, &global_part, true, -1, &location)){ jump = jump_location_store(app, location); } else{ @@ -462,17 +456,35 @@ CUSTOM_COMMAND_SIG(goto_prev_error){ } }while(skip_this_jump(prev_location, jump)); prev_location = jump; + end_temp_memory(temp); } CUSTOM_COMMAND_SIG(goto_first_error){ + Temp_Memory temp = begin_temp_memory(&global_part); View_Summary active_view = app->get_active_view(app, AccessAll); app->view_set_cursor(app, &active_view, seek_pos(0), true); - Jump_Location location; - goto_error(app, true, 1, &location); + Jump_Location location = {0}; + seek_error(app, &global_part, true, 1, &location); prev_location = jump_location_store(app, location); + end_temp_memory(temp); } +CUSTOM_COMMAND_SIG(goto_postion_at_cursor){ + Temp_Memory temp = begin_temp_memory(&global_part); + View_Summary view = app->get_active_view(app, AccessProtected); + + Jump_Location location = {0}; + goto_error(app, &global_part, + &view, view.cursor.line, + &location, false); + + exec_command(app, change_active_panel); + + view = app->get_active_view(app, AccessAll); + jump_to_location(app, &view, &location); + end_temp_memory(temp); +} #endif diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index bb47be5c..1ec09adc 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -15,8 +15,8 @@ // Memory // -static Partition part; -static General_Memory general; +static Partition global_part; +static General_Memory global_general; void init_memory(Application_Links *app){ @@ -25,10 +25,10 @@ init_memory(Application_Links *app){ void *part_mem = app->memory_allocate(app, part_size); - part = make_part(part_mem, part_size); + global_part = make_part(part_mem, part_size); void *general_mem = app->memory_allocate(app, general_size); - general_memory_open(&general, general_mem, general_size); + general_memory_open(&global_general, general_mem, general_size); } // @@ -534,6 +534,30 @@ CUSTOM_COMMAND_SIG(delete_range){ // Basic Navigation // +CUSTOM_COMMAND_SIG(center_view){ + View_Summary view = app->get_active_view(app, AccessProtected); + + i32_Rect region = view.file_region; + GUI_Scroll_Vars scroll = view.scroll_vars; + + float h = (float)(region.y1 - region.y0); + float y = get_view_y(view); + y = y - h*.5f; + scroll.target_y = (int32_t)(y + .5f); + app->view_set_scroll(app, &view, scroll); +} + +CUSTOM_COMMAND_SIG(left_adjust_view){ + View_Summary view = app->get_active_view(app, AccessProtected); + + GUI_Scroll_Vars scroll = view.scroll_vars; + + float x = get_view_x(view); + x = x - 30.f; + scroll.target_x = (int32_t)(x + .5f); + app->view_set_scroll(app, &view, scroll); +} + int get_relative_xy(View_Summary *view, int x, int y, float *x_out, float *y_out){ int result = false; @@ -2183,6 +2207,115 @@ CUSTOM_COMMAND_SIG(eol_nixify){ #include "4coder_table.cpp" #include "4coder_search.cpp" +CUSTOM_COMMAND_SIG(list_all_locations){ + Query_Bar string; + char string_space[1024]; + string.prompt = make_lit_string("List Locations For: "); + string.string = make_fixed_width_string(string_space); + + if (!query_user_string(app, &string)) return; + if (string.string.size == 0) return; + + Search_Set set = {0}; + Search_Iter iter = {0}; + + search_iter_init(&global_general, &iter, string.string.size); + copy(&iter.word, string.string); + + int buffer_count = app->get_buffer_count(app); + search_set_init(&global_general, &set, buffer_count); + + Search_Range *ranges = set.ranges; + + { + View_Summary view = app->get_active_view(app, AccessProtected); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, AccessProtected); + + int j = 0; + if (buffer.exists){ + ranges[0].type = SearchRange_FrontToBack; + ranges[0].flags = 0; + ranges[0].buffer = buffer.buffer_id; + ranges[0].start = 0; + ranges[0].size = buffer.size; + 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].flags = 0; + ranges[j].buffer = buffer_it.buffer_id; + ranges[j].start = 0; + ranges[j].size = buffer_it.size; + ++j; + } + } + set.count = j; + } + + Buffer_Summary search_buffer = app->get_buffer_by_name(app, literal("*search*"), AccessAll); + if (!search_buffer.exists){ + search_buffer = app->create_buffer(app, literal("*search*"), BufferCreate_AlwaysNew); + app->buffer_set_setting(app, &search_buffer, BufferSetting_Unimportant, true); + app->buffer_set_setting(app, &search_buffer, BufferSetting_ReadOnly, true); + } + else{ + app->buffer_replace_range(app, &search_buffer, 0, search_buffer.size, 0, 0); + } + + Temp_Memory temp = begin_temp_memory(&global_part); + Partition line_part = partition_sub_part(&global_part, (4 << 10)); + char *str = (char*)partition_current(&global_part); + int size = 0; + for (;;){ + Search_Match match = search_next_match(app, &set, &iter); + if (match.found_match){ + Partial_Cursor word_pos = {0}; + if (app->buffer_compute_cursor(app, &match.buffer, seek_pos(match.start), &word_pos)){ + int file_len = match.buffer.file_name_len; + int line_num_len = int_to_str_size(word_pos.line); + int column_num_len = int_to_str_size(word_pos.character); + + Temp_Memory line_temp = begin_temp_memory(&line_part); + String line_str = {0}; + read_line(app, &line_part, &match.buffer, word_pos.line, &line_str); + line_str = skip_chop_whitespace(line_str); + + int str_len = file_len + 1 + line_num_len + 1 + column_num_len + 1 + 1 + line_str.size + 1; + + char *spare = push_array(&global_part, char, str_len); + size += str_len; + + String out_line = make_string(spare, 0, str_len); + append(&out_line, make_string(match.buffer.file_name, file_len)); + append(&out_line, ':'); + append_int_to_str(&out_line, word_pos.line); + append(&out_line, ':'); + append_int_to_str(&out_line, word_pos.character); + append(&out_line, ':'); + append(&out_line, ' '); + append(&out_line, line_str); + append(&out_line, '\n'); + + end_temp_memory(line_temp); + } + } + else{ + break; + } + } + + app->buffer_replace_range(app, &search_buffer, 0, 0, str, size); + + View_Summary view = app->get_active_view(app, AccessAll); + app->view_set_buffer(app, &view, search_buffer.buffer_id, 0); + + end_temp_memory(temp); +} + struct Word_Complete_State{ Search_Set set; Search_Iter iter; @@ -2254,7 +2387,7 @@ CUSTOM_COMMAND_SIG(word_complete){ // NOTE(allen): Initialize the search iterator // with the partial word. complete_state.initialized = true; - search_iter_init(app, &complete_state.iter, size); + search_iter_init(&global_general, &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; @@ -2262,10 +2395,11 @@ CUSTOM_COMMAND_SIG(word_complete){ // 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_set_init(&global_general, &complete_state.set, buffer_count); Search_Range *ranges = complete_state.set.ranges; ranges[0].type = SearchRange_Wave; + ranges[0].flags = SearchFlag_MatchStartOfIdentifier; ranges[0].buffer = buffer.buffer_id; ranges[0].start = 0; ranges[0].size = buffer.size; @@ -2278,6 +2412,7 @@ CUSTOM_COMMAND_SIG(word_complete){ app->get_buffer_next(app, &buffer_it, AccessAll)){ if (buffer.buffer_id != buffer_it.buffer_id){ ranges[j].type = SearchRange_FrontToBack; + ranges[j].flags = SearchFlag_MatchStartOfIdentifier; ranges[j].buffer = buffer_it.buffer_id; ranges[j].start = 0; ranges[j].size = buffer_it.size; @@ -2287,9 +2422,9 @@ CUSTOM_COMMAND_SIG(word_complete){ complete_state.set.count = j; // NOTE(allen): Initialize the search hit table. - search_hits_init(app, &complete_state.hits, &complete_state.str, + search_hits_init(&global_general, &complete_state.hits, &complete_state.str, 100, (4 << 10)); - search_hit_add(app, &complete_state.hits, &complete_state.str, + search_hit_add(&global_general, &complete_state.hits, &complete_state.str, complete_state.iter.word.str, complete_state.iter.word.size); @@ -2312,13 +2447,13 @@ CUSTOM_COMMAND_SIG(word_complete){ if (match.found_match){ int match_size = match.end - match.start; - Temp_Memory temp = begin_temp_memory(&part); - char *spare = push_array(&part, char, match_size); + Temp_Memory temp = begin_temp_memory(&global_part); + char *spare = push_array(&global_part, char, 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, + if (search_hit_add(&global_general, &complete_state.hits, &complete_state.str, spare, match_size)){ app->buffer_replace_range(app, &buffer, word_start, word_end, spare, match_size); @@ -2337,9 +2472,9 @@ CUSTOM_COMMAND_SIG(word_complete){ complete_state.iter.pos = 0; complete_state.iter.i = 0; - search_hits_init(app, &complete_state.hits, &complete_state.str, + search_hits_init(&global_general, &complete_state.hits, &complete_state.str, 100, (4 << 10)); - search_hit_add(app, &complete_state.hits, &complete_state.str, + search_hit_add(&global_general, &complete_state.hits, &complete_state.str, complete_state.iter.word.str, complete_state.iter.word.size); diff --git a/4coder_helper.h b/4coder_helper.h index c11b5409..f7e5de5f 100644 --- a/4coder_helper.h +++ b/4coder_helper.h @@ -419,8 +419,11 @@ get_active_buffer(Application_Links *app, unsigned int access){ 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); + char result = ' '; + *buffer = app->get_buffer(app, buffer->buffer_id, AccessAll); + if (pos >= 0 && pos < buffer->size){ + app->buffer_read_range(app, buffer, pos, pos+1, &result); + } return(result); } @@ -469,4 +472,38 @@ view_open_file(Application_Links *app, View_Summary *view, return(result); } +static int +read_line(Application_Links *app, + Partition *part, + Buffer_Summary *buffer, + int line, + String *str){ + + Partial_Cursor begin = {0}; + Partial_Cursor end = {0}; + + int success = false; + + if (app->buffer_compute_cursor(app, buffer, + seek_line_char(line, 1), &begin)){ + if (app->buffer_compute_cursor(app, buffer, + seek_line_char(line, 65536), &end)){ + if (begin.line == line){ + if (0 <= begin.pos && begin.pos <= end.pos && end.pos <= buffer->size){ + int size = (end.pos - begin.pos); + *str = make_string(push_array(part, char, size+1), size+1); + if (str->str){ + success = true; + app->buffer_read_range(app, buffer, begin.pos, end.pos, str->str); + str->size = size; + terminate_with_null(str); + } + } + } + } + } + + return(success); +} + #endif diff --git a/4coder_search.cpp b/4coder_search.cpp index a0b92a10..4e411bd8 100644 --- a/4coder_search.cpp +++ b/4coder_search.cpp @@ -1,431 +1,460 @@ - -#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; -}; - -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*)general_memory_allocate(&general, str_max); - iter->word.memory_size = str_max; - } - else if (iter->word.memory_size < size){ - iter->word.str = (char*)general_memory_reallocate_nocopy(&general, iter->word.str, str_max); - iter->word.memory_size = str_max; - } - iter->i = 0; - iter->range_initialized = 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*)general_memory_allocate(&general, sizeof(Search_Range)*max); - set->max = max; - } - else if (set->max < range_count){ - set->ranges = (Search_Range*)general_memory_reallocate_nocopy( - &general, 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 = general_memory_allocate(&general, mem_size); - } - else{ - mem = general_memory_reallocate_nocopy(&general, hits->hash_array, mem_size); - } - 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 = 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); - str->max = str_size; - } - else if (str->max < str_size){ - str->space = (char*)general_memory_reallocate_nocopy(&general, 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*)general_memory_reallocate( - &general, space->space, space->new_pos, 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); - general_memory_free(&general, 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; - *pos = end_pos + 1; - } - } - else{ - found_match = FindResult_PastEnd; - *pos = end_pos + 1; - } - - *result_ptr = result; - - return(found_match); -} - -static int -search_front_to_back(Application_Links *app, - Search_Range *range, - String word, - int *pos, - Search_Match *result_ptr){ - int found_match = FindResult_None; - for (;found_match == FindResult_None;){ - found_match = search_front_to_back_step(app, range, word, pos, result_ptr); - } - 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 int -search_back_to_front(Application_Links *app, - Search_Range *range, - String word, - int *pos, - Search_Match *result_ptr){ - int found_match = FindResult_None; - for (;found_match == FindResult_None;){ - found_match = search_back_to_front_step(app, range, word, pos, result_ptr); - } - 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; - - 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(app, range, - iter.word, - &iter.pos, - &result); - }break; - - case SearchRange_BackToFront: - { - find_result = - search_back_to_front(app, range, - iter.word, - &iter.back_pos, - &result); - }break; - - case SearchRange_Wave: - { - Search_Match forward_match = {0}; - Search_Match backward_match = {0}; - - int forward_result = FindResult_PastEnd; - int backward_result = FindResult_PastEnd; - - if (iter.pos < range->start + range->size){ - forward_result = search_front_to_back(app, range, - iter.word, - &iter.pos, - &forward_match); - } - - if (iter.back_pos > range->start){ - backward_result = search_back_to_front(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 = (range->mid_start - backward_match.end); - - if (backward_distance < forward_distance){ - iter.pos = forward_match.start; - result = backward_match; - } - else{ - iter.back_pos = backward_match.start; - result = forward_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:; - - *it_ptr = iter; - - return(result); -} - -#endif + +#ifndef FCODER_SEARCH +#define FCODER_SEARCH + +enum Search_Range_Type{ + SearchRange_FrontToBack, + SearchRange_BackToFront, + SearchRange_Wave, +}; + +enum Search_Range_Flag{ + SearchFlag_MatchStartOfIdentifier = 0x1, +}; + +struct Search_Range{ + int type; + unsigned int flags; + 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; +}; + +static void +search_iter_init(General_Memory *general, Search_Iter *iter, int size){ + int str_max = size*2; + if (iter->word.str == 0){ + iter->word.str = (char*)general_memory_allocate(general, str_max); + iter->word.memory_size = str_max; + } + else if (iter->word.memory_size < size){ + iter->word.str = (char*)general_memory_reallocate_nocopy(general, iter->word.str, str_max); + iter->word.memory_size = str_max; + } + iter->i = 0; + iter->range_initialized = 0; +} + +static void +search_set_init(General_Memory *general, Search_Set *set, int range_count){ + int max = range_count*2; + + if (set->ranges == 0){ + set->ranges = (Search_Range*)general_memory_allocate(general, sizeof(Search_Range)*max); + set->max = max; + } + else if (set->max < range_count){ + set->ranges = (Search_Range*)general_memory_reallocate_nocopy( + general, set->ranges, sizeof(Search_Range)*max); + set->max = max; + } + + set->count = range_count; +} + +static void +search_hits_table_alloc(General_Memory *general, 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 = general_memory_allocate(general, mem_size); + } + else{ + mem = general_memory_reallocate_nocopy(general, hits->hash_array, mem_size); + } + table_init_memory(hits, mem, table_size, sizeof(Offset_String)); +} + +static void +search_hits_init(General_Memory *general, Table *hits, String_Space *str, int table_size, int str_size){ + if (hits->hash_array == 0){ + search_hits_table_alloc(general, hits, table_size); + } + else{ + int mem_size = table_required_mem_size(table_size, sizeof(Offset_String)); + void *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); + str->max = str_size; + } + else if (str->max < str_size){ + str->space = (char*)general_memory_reallocate_nocopy(general, str->space, str_size); + str->max = str_size; + } + + str->pos = str->new_pos = 0; + table_clear(hits); +} + +static int +search_hit_add(General_Memory *general, 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*)general_memory_reallocate( + general, space->space, space->new_pos, 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(general, &new_hits, hits->max*2); + table_clear(&new_hits); + table_rehash(hits, &new_hits, space->space, tbl_offset_string_hash, tbl_offset_string_compare); + general_memory_free(general, 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 +match_check(Application_Links *app, Search_Range *range, int *pos, Search_Match *result_ptr, String word){ + int found_match = FindResult_None; + + Search_Match result = *result_ptr; + int end_pos = range->start + range->size; + + if (range->flags & SearchFlag_MatchStartOfIdentifier){ + char 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; + found_match = FindResult_FoundMatch; + } + else{ + found_match = FindResult_PastEnd; + } + } + } + else{ + char prev = buffer_get_char(app, &result.buffer, result.start - 1); + + if (!char_is_alpha_numeric(prev)){ + result.end = result.start + word.size; + if (result.end <= end_pos){ + char next = buffer_get_char(app, &result.buffer, result.end); + if (!char_is_alpha_numeric(next)){ + result.found_match = true; + found_match = FindResult_FoundMatch; + } + } + else{ + found_match = FindResult_PastEnd; + } + } + } + + *result_ptr = result; + + return(found_match); +} + +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; + found_match = match_check(app, range, pos, &result, word); + if (found_match == FindResult_FoundMatch){ + *pos = result.end; + } + } + else{ + found_match = FindResult_PastEnd; + *pos = end_pos + 1; + } + } + else{ + found_match = FindResult_PastEnd; + *pos = end_pos + 1; + } + + *result_ptr = result; + + return(found_match); +} + +static int +search_front_to_back(Application_Links *app, + Search_Range *range, + String word, + int *pos, + Search_Match *result_ptr){ + int found_match = FindResult_None; + for (;found_match == FindResult_None;){ + found_match = search_front_to_back_step(app, range, word, pos, result_ptr); + } + 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; + + 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); + + // TODO(allen): deduplicate the match checking code. + if (result.start >= range->start){ + *pos = result.start - 1; + found_match = match_check(app, range, pos, &result, word); + if (found_match == FindResult_FoundMatch){ + *pos = result.start - word.size; + } + } + else{ + found_match = FindResult_PastEnd; + } + } + else{ + found_match = FindResult_PastEnd; + } + + *result_ptr = result; + + return(found_match); +} + +static int +search_back_to_front(Application_Links *app, + Search_Range *range, + String word, + int *pos, + Search_Match *result_ptr){ + int found_match = FindResult_None; + for (;found_match == FindResult_None;){ + found_match = search_back_to_front_step(app, range, word, pos, result_ptr); + } + 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; + + 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(app, range, + iter.word, + &iter.pos, + &result); + }break; + + case SearchRange_BackToFront: + { + find_result = + search_back_to_front(app, range, + iter.word, + &iter.back_pos, + &result); + }break; + + case SearchRange_Wave: + { + Search_Match forward_match = {0}; + Search_Match backward_match = {0}; + + int forward_result = FindResult_PastEnd; + int backward_result = FindResult_PastEnd; + + if (iter.pos < range->start + range->size){ + forward_result = search_front_to_back(app, range, + iter.word, + &iter.pos, + &forward_match); + } + + if (iter.back_pos > range->start){ + backward_result = search_back_to_front(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 = (range->mid_start - backward_match.end); + + if (backward_distance < forward_distance){ + iter.pos = forward_match.start; + result = backward_match; + } + else{ + iter.back_pos = backward_match.start; + result = forward_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:; + + *it_ptr = iter; + + return(result); +} + +#endif diff --git a/4coder_types.h b/4coder_types.h index d3e6f7ff..e69e7543 100644 --- a/4coder_types.h +++ b/4coder_types.h @@ -51,14 +51,6 @@ ENUM(uint64_t, Command_ID){ /* DOC(cmdid_null is set aside to always be zero and is not associated with any command.) */ cmdid_null, - /* DOC(cmdid_center_view centers the view vertically on the cursor.) */ - cmdid_center_view, - /* DOC(cmdid_left_adjust_view adjusts the view to be just left of the cursor's position.) */ - cmdid_left_adjust_view, - - /* DOC(cmdid_word_complete begins or continues cycling through completions for a partial word.) */ - cmdid_word_complete, - /* DOC(cmdid_undo performs a standard undo behavior.) */ cmdid_undo, /* DOC(cmdid_redo reperforms an edit that was undone.) */ @@ -72,16 +64,17 @@ ENUM(uint64_t, Command_ID){ cmdid_interactive_new, /* DOC(cmdid_interactive_open begins an interactive dialogue to open a file into a buffer.) */ cmdid_interactive_open, - /* DOC(cmdid_reopen reloads the active buffer's associated file and discards the old buffer contents for the reloaded file.) */ - cmdid_reopen, - /* DOC(cmdid_save saves the buffer's contents into the associated file.) */ - cmdid_save, /* DOC(cmdid_save_as does not currently work and is likely to be removed rather that fixed.) */ cmdid_save_as, /* DOC(cmdid_interactive_switch_buffer begins an interactive dialogue to choose an open buffer to swap into the active view.) */ cmdid_interactive_switch_buffer, /* DOC(cmdid_interactive_kill_buffer begins an interactive dialogue to choose an open buffer to kill.) */ cmdid_interactive_kill_buffer, + + /* DOC(cmdid_reopen reloads the active buffer's associated file and discards the old buffer contents for the reloaded file.) */ + cmdid_reopen, + /* DOC(cmdid_save saves the buffer's contents into the associated file.) */ + cmdid_save, /* DOC(cmdid_kill_buffer tries to kill the active buffer.) */ cmdid_kill_buffer, @@ -157,9 +150,18 @@ ENUM(int32_t, Buffer_Setting_ID){ active when a buffer is active.) */ BufferSetting_MapID, - /* DOC(The BufferSetting_Eol setting spcifies how line ends should be saved to the backing file. + /* DOC(The BufferSetting_Eol setting specifies how line ends should be saved to the backing file. A 1 indicates dos endings "\r\n" and a 0 indicates nix endings "\n".) */ BufferSetting_Eol, + + /* DOC(The BufferSetting_Unimportant setting marks a buffer so that it's dirty state will be completely + ignored. This means the "dirty" star is hidden and the buffer can be closed without presenting an + "are you sure" dialogue screen.) */ + BufferSetting_Unimportant, + + /* DOC(The BufferSetting_ReadOnly setting marks a buffer so that it can only be returned from buffer + access calls that include an AccessProtected flag.) */ + BufferSetting_ReadOnly, }; /* DOC(A View_Setting_ID names a setting in a view.) */ @@ -185,7 +187,7 @@ ENUM(int32_t, View_Setting_ID){ FLAGENUM(Buffer_Create_Flag){ /* DOC(BufferCreate_Background is not currently implemented.) */ BufferCreate_Background = 0x1, - /* DOC(When BufferCreate_AlwaysNew is et it indicates the buffer should be + /* DOC(When BufferCreate_AlwaysNew is set it indicates the buffer should be cleared to empty even if it's associated file already has content.) */ BufferCreate_AlwaysNew = 0x2, }; @@ -485,7 +487,8 @@ struct GUI_Scroll_Vars{ }; /* DOC(Full_Cursor describes the position of a cursor in every buffer -coordinate system supported by 4coder.) +coordinate system supported by 4coder. This cursor type requires that +the buffer is associated with a view to give the x/y values meaning.) DOC_SEE(4coder_Buffer_Positioning_System) */ struct Full_Cursor{ /* DOC(This field contains the cursor's position in absolute positioning.) */ @@ -504,6 +507,20 @@ struct Full_Cursor{ float wrapped_y; }; +/* DOC(Partial_Cursor describes the position of a cursor in all of +the coordinate systems that a invariant to the View. In other words +the coordinate systems available here can be used on a buffer that is +not currently associated with a View.) +DOC_SEE(4coder_Buffer_Positioning_System) */ +struct Partial_Cursor{ + /* DOC(This field contains the cursor's position in absolute positioning.) */ + int32_t pos; + /* DOC(This field contains the number of the line where the cursor is located. This field is one based.) */ + int32_t line; + /* DOC(This field contains the number of the column where the cursor is located. This field is one based.) */ + int32_t character; +}; + /* DOC(Buffer_Seek describes the destination of a seek operation. There are helpers for concisely creating Buffer_Seek structs. They can be found in 4coder_buffer_types.h.) DOC_SEE(Buffer_Seek_Type) @@ -596,7 +613,9 @@ struct Buffer_Summary{ }; /* DOC(View_Summary acts as a handle to a view and describes the state of the view.) -DOC_SEE(Access_Flag)*/ +DOC_SEE(Access_Flag) +DOC_SEE(Full_Cursor) +*/ struct View_Summary{ /* DOC( This field indicates whether the View_Summary describes a view that is open in 4coder. @@ -617,12 +636,10 @@ struct View_Summary{ /* DOC(If this is not a null summary, this describes the position of the cursor.) - DOC_SEE(Full_Cursor) */ Full_Cursor cursor; /* DOC(If this is not a null summary, this describes the position of the mark.) - DOC_SEE(Full_Cursor) */ Full_Cursor mark; /* DOC(If this is not a null summary, this is the x position that is maintained in vertical navigation.) */ @@ -634,9 +651,9 @@ struct View_Summary{ /* DOC(If this is not a null summary, this indicates that the view is set to highlight white space.) */ bool32 show_whitespace; - /* DOC(This feature is not fully implemented yet.) */ + /* DOC(If this is not a null summary, this describes the screen position in which this view's buffer is displayed.) */ i32_Rect file_region; - /* DOC(This feature is not fully implemented yet.) */ + /* DOC(If this is not a null summary, this describes the scrolling position inside the view.) */ GUI_Scroll_Vars scroll_vars; }; diff --git a/4ed.cpp b/4ed.cpp index 6e9dacce..e040032c 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -34,15 +34,6 @@ struct CLI_List{ i32 count, max; }; -struct Complete_State{ - Search_Set set; - Search_Iter iter; - Table hits; - String_Space str; - i32 word_start, word_end; - b32 initialized; -}; - struct Command_Data{ Models *models; struct App_Vars *vars; @@ -169,7 +160,6 @@ struct App_Vars{ App_State state; App_State_Resizing resizing; - Complete_State complete_state; Command_Data command_data; @@ -281,223 +271,6 @@ COMMAND_DECL(null){ AllowLocal(command); } -internal i32 -seek_token_left(Cpp_Token_Stack *tokens, i32 pos){ - Cpp_Get_Token_Result get = cpp_get_token(tokens, pos); - if (get.token_index == -1){ - get.token_index = 0; - } - - Cpp_Token *token = tokens->tokens + get.token_index; - if (token->start == pos && get.token_index > 0){ - --token; - } - - return token->start; -} - -internal i32 -seek_token_right(Cpp_Token_Stack *tokens, i32 pos){ - Cpp_Get_Token_Result get = cpp_get_token(tokens, pos); - if (get.in_whitespace){ - ++get.token_index; - } - if (get.token_index >= tokens->count){ - get.token_index = tokens->count-1; - } - - Cpp_Token *token = tokens->tokens + get.token_index; - return token->start + token->size; -} - -COMMAND_DECL(center_view){ - REQ_READABLE_VIEW(view); - REQ_FILE(file, view); - - Assert(view->edit_pos); - - f32 h = view_file_height(view); - f32 y = view->edit_pos->cursor.wrapped_y; - if (view->file_data.unwrapped_lines){ - y = view->edit_pos->cursor.unwrapped_y; - } - - y = clamp_bottom(0.f, y - h*.5f); - view->edit_pos->scroll.target_y = ROUND32(y); -} - -COMMAND_DECL(left_adjust_view){ - REQ_READABLE_VIEW(view); - REQ_FILE(file, view); - - Assert(view->edit_pos); - - f32 x = view->edit_pos->cursor.wrapped_x; - if (view->file_data.unwrapped_lines){ - x = view->edit_pos->cursor.unwrapped_x; - } - - x = clamp_bottom(0.f, x - 30.f); - view->edit_pos->scroll.target_x = ROUND32(x); -} - -COMMAND_DECL(word_complete){ - USE_MODELS(models); - USE_VARS(vars); - REQ_OPEN_VIEW(view); - REQ_FILE(file, view); - - Assert(view->edit_pos); - - Partition *part = &models->mem.part; - General_Memory *general = &models->mem.general; - Working_Set *working_set = &models->working_set; - Complete_State *complete_state = &vars->complete_state; - Search_Range *ranges = 0; - - Buffer_Type *buffer = &file->state.buffer; - i32 size_of_buffer = buffer_size(buffer); - - i32 cursor_pos = 0; - i32 word_start = 0; - i32 word_end = 0; - char c = 0; - - char *spare = 0; - i32 size = 0; - - b32 do_init = false; - if (view->mode.rewrite != 2){ - do_init = true; - } - view->next_mode.rewrite = 2; - if (complete_state->initialized == 0){ - do_init = true; - } - - if (do_init){ - word_end = view->edit_pos->cursor.pos; - word_start = word_end; - cursor_pos = word_end - 1; - - // TODO(allen): macros for these buffer loops and some method - // of breaking out of them. - for (Buffer_Backify_Type loop = buffer_backify_loop(buffer, cursor_pos, 0); - buffer_backify_good(&loop); - buffer_backify_next(&loop)){ - i32 end = loop.absolute_pos; - char *data = loop.data - loop.absolute_pos; - for (; cursor_pos >= end; --cursor_pos){ - c = data[cursor_pos]; - if (char_is_alpha(c)){ - word_start = cursor_pos; - } - else if (!char_is_numeric(c)){ - goto double_break; - } - } - } - double_break:; - - size = word_end - word_start; - - if (size == 0){ - complete_state->initialized = 0; - return; - } - - complete_state->initialized = 1; - search_iter_init(general, &complete_state->iter, size); - buffer_stringify(buffer, word_start, word_end, complete_state->iter.word.str); - complete_state->iter.word.size = size; - - { - File_Node *node, *used_nodes; - Editing_File *file_ptr; - i32 buffer_count, j; - - buffer_count = working_set->file_count; - search_set_init(general, &complete_state->set, buffer_count + 1); - ranges = complete_state->set.ranges; - ranges[0].buffer = buffer; - ranges[0].start = 0; - ranges[0].size = word_start; - - ranges[1].buffer = buffer; - ranges[1].start = word_end; - ranges[1].size = size_of_buffer - word_end; - - used_nodes = &working_set->used_sentinel; - j = 2; - for (dll_items(node, used_nodes)){ - file_ptr = (Editing_File*)node; - if (file_ptr != file){ - ranges[j].buffer = &file_ptr->state.buffer; - ranges[j].start = 0; - ranges[j].size = buffer_size(ranges[j].buffer); - ++j; - } - } - complete_state->set.count = j; - } - - search_hits_init(general, &complete_state->hits, &complete_state->str, 100, Kbytes(4)); - search_hit_add(general, &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; - } - - if (size > 0){ - for (;;){ - i32 match_size = 0; - Search_Match match = - search_next_match(part, &complete_state->set, &complete_state->iter); - - if (match.found_match){ - Temp_Memory temp = begin_temp_memory(part); - match_size = match.end - match.start; - spare = (char*)push_array(part, char, match_size); - buffer_stringify(match.buffer, match.start, match.end, spare); - - if (search_hit_add(general, &complete_state->hits, &complete_state->str, spare, match_size)){ - view_replace_range(system, models, view, word_start, word_end, spare, match_size); - view_cursor_move(view, word_start + match_size); - - 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); - } - else{ - complete_state->iter.pos = 0; - complete_state->iter.i = 0; - - search_hits_init(general, &complete_state->hits, &complete_state->str, 100, Kbytes(4)); - search_hit_add(general, &complete_state->hits, &complete_state->str, - complete_state->iter.word.str, complete_state->iter.word.size); - - match_size = complete_state->iter.word.size; - view_replace_range(system, models, view, word_start, word_end, - complete_state->iter.word.str, match_size); - view_cursor_move(view, word_start + match_size); - - complete_state->word_end = word_start + match_size; - complete_state->set.ranges[1].start = word_start + match_size; - break; - } - } - } -} - // TODO(allen): FIX THIS SHIT! COMMAND_DECL(undo){ USE_MODELS(models); @@ -1027,11 +800,6 @@ setup_command_table(){ #define SET(n) command_table[cmdid_##n] = command_##n SET(null); - SET(center_view); - SET(left_adjust_view); - - SET(word_complete); - SET(undo); SET(redo); SET(history_backward); diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index bada3b39..805a628b 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -447,6 +447,7 @@ This call begins a loop across all the buffers. If the buffer returned does not exist, the loop is finished. Buffers should not be killed durring a buffer loop. ) +DOC_SEE(Buffer_Summary) DOC_SEE(Access_Flag) DOC_SEE(get_buffer_next) */{ @@ -474,6 +475,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. ) +DOC_SEE(Buffer_Summary) DOC_SEE(Access_Flag) DOC_SEE(get_buffer_first) */{ @@ -491,6 +493,7 @@ Get_Buffer(Application_Links *app, Buffer_ID buffer_id, Access_Flag access)/* DOC_PARAM(buffer_id, The parameter buffer_id specifies which buffer to try to get.) DOC_PARAM(access, The access parameter determines what levels of protection this call can access.) DOC_RETURN(This call returns a summary that describes the indicated buffer if it exists and is accessible.) +DOC_SEE(Buffer_Summary) DOC_SEE(Access_Flag) DOC_SEE(Buffer_ID) */{ @@ -516,6 +519,7 @@ DOC_PARAM(name, The name parameter specifies the buffer name to try to get. The DOC_PARAM(len, The len parameter specifies the length of the name string.) DOC_PARAM(access, The access parameter determines what levels of protection this call can access.) DOC_RETURN(This call returns a summary that describes the indicated buffer if it exists and is accessible.) +DOC_SEE(Buffer_Summary) DOC_SEE(Access_Flag) */{ Command_Data *cmd = (Command_Data*)app->cmd_context; @@ -534,6 +538,35 @@ DOC_SEE(Access_Flag) return(buffer); } +internal i32 +seek_token_left(Cpp_Token_Stack *tokens, i32 pos){ + Cpp_Get_Token_Result get = cpp_get_token(tokens, pos); + if (get.token_index == -1){ + get.token_index = 0; + } + + Cpp_Token *token = tokens->tokens + get.token_index; + if (token->start == pos && get.token_index > 0){ + --token; + } + + return token->start; +} + +internal i32 +seek_token_right(Cpp_Token_Stack *tokens, i32 pos){ + Cpp_Get_Token_Result get = cpp_get_token(tokens, pos); + if (get.in_whitespace){ + ++get.token_index; + } + if (get.token_index >= tokens->count){ + get.token_index = tokens->count-1; + } + + Cpp_Token *token = tokens->tokens + get.token_index; + return token->start + token->size; +} + API_EXPORT int32_t Buffer_Boundary_Seek(Application_Links *app, Buffer_Summary *buffer, int32_t start_pos, bool32 seek_forward, Seek_Boundary_Flag flags)/* DOC_PARAM(buffer, The buffer parameter specifies the buffer through which to seek.) @@ -712,6 +745,32 @@ DOC_SEE(4coder_Buffer_Positioning_System) return(result); } +API_EXPORT bool32 +Buffer_Compute_Cursor(Application_Links *app, Buffer_Summary *buffer, Buffer_Seek seek, Partial_Cursor *cursor_out)/* +DOC_PARAM(buffer, The buffer parameter specifies the buffer on which to run the cursor computation.) +DOC_PARAM(seek, The seek parameter specifies the target position for the seek.) +DOC_PARAM(cursor_out, On success this struct is filled with the result of the seek.) +DOC_RETURN(This call returns non-zero on success.) +DOC(Computes a Partial_Cursor for the given seek position with no side effects. +The seek position must be one of the types supported by Partial_Cursor. Those +types are absolute position and line,column position.) +DOC_SEE(Buffer_Seek) +DOC_SEE(Partial_Cursor) +*/{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + Editing_File *file = imp_get_file(cmd, buffer); + bool32 result = false; + + if (file){ + if (file_compute_cursor(file, seek, cursor_out)){ + result = true; + fill_buffer_summary(buffer, file, cmd); + } + } + + return(result); +} + API_EXPORT bool32 Buffer_Batch_Edit(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type)/* DOC_PARAM(str, This parameter provides all of the source string for the edits in the batch.) @@ -844,6 +903,26 @@ DOC_SEE(Buffer_Setting_ID) file->settings.dos_write_mode = value; file->state.last_4ed_edit_time = system->now_time_stamp(); }break; + + case BufferSetting_Unimportant: + { + if (value){ + file->settings.unimportant = true; + } + else{ + file->settings.unimportant = false; + } + }break; + + case BufferSetting_ReadOnly: + { + if (value){ + file->settings.read_only = true; + } + else{ + file->settings.read_only = false; + } + }break; } fill_buffer_summary(buffer, file, cmd); } @@ -907,6 +986,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. ) +DOC_SEE(Buffer_Summary) DOC_SEE(Buffer_Create_Flag) */{ Command_Data *cmd = (Command_Data*)app->cmd_context; @@ -1508,8 +1588,30 @@ DOC_SEE(Buffer_Seek) seek.character = 1; } Full_Cursor cursor = view_compute_cursor(vptr, seek); - view_set_cursor(vptr, cursor, - set_preferred_x, vptr->file_data.unwrapped_lines); + view_set_cursor(vptr, cursor, set_preferred_x, + vptr->file_data.unwrapped_lines); + fill_view_summary(view, vptr, cmd); + } + } + + return(result); +} + +API_EXPORT bool32 +View_Set_Scroll(Application_Links *app, View_Summary *view, GUI_Scroll_Vars scroll)/* +DOC(TODO) +DOC_SEE(GUI_Scroll_Vars) +*/{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + View *vptr = imp_get_view(cmd, view); + Editing_File *file = 0; + bool32 result = false; + + if (vptr){ + file = vptr->file_data.file; + if (file && !file->is_loading){ + result = true; + view_set_scroll(vptr, scroll); fill_view_summary(view, vptr, cmd); } } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 1376751d..f1244c10 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -377,6 +377,40 @@ view_cursor_limits(View *view){ return(limits); } +inline Partial_Cursor +file_compute_cursor_from_pos(Editing_File *file, i32 pos){ + Partial_Cursor result = buffer_partial_from_pos(&file->state.buffer, pos); + return(result); +} + +inline Partial_Cursor +file_compute_cursor_from_line_character(Editing_File *file, i32 line, i32 character){ + Partial_Cursor result = buffer_partial_from_line_character(&file->state.buffer, line, character); + return(result); +} + +inline b32 +file_compute_cursor(Editing_File *file, Buffer_Seek seek, Partial_Cursor *cursor){ + b32 result = true; + switch (seek.type){ + case buffer_seek_pos: + { + *cursor = file_compute_cursor_from_pos(file, seek.pos); + }break; + + case buffer_seek_line_char: + { + *cursor = file_compute_cursor_from_line_character(file, seek.line, seek.character); + }break; + + default: + { + result = false; + }break; + } + return(result); +} + inline Full_Cursor view_compute_cursor_from_pos(View *view, i32 pos){ Editing_File *file = view->file_data.file; @@ -5982,196 +6016,6 @@ file_view_free_buffers(View *view){ view->gui_mem = 0; } -struct Search_Range{ - Buffer_Type *buffer; - i32 start, size; -}; - -struct Search_Set{ - Search_Range *ranges; - i32 count, max; -}; - -struct Search_Iter{ - String word; - i32 pos; - i32 i; -}; - -struct Search_Match{ - Buffer_Type *buffer; - i32 start, end; - b32 found_match; -}; - -internal void -search_iter_init(General_Memory *general, Search_Iter *iter, i32 size){ - i32 str_max; - - if (iter->word.str == 0){ - str_max = size*2; - 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); - iter->word.memory_size = str_max; - } - - iter->i = 0; - iter->pos = 0; -} - -internal void -search_set_init(General_Memory *general, Search_Set *set, i32 set_count){ - i32 max; - - if (set->ranges == 0){ - max = set_count*2; - 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); - set->max = max; - } - - set->count = set_count; -} - -internal void -search_hits_table_alloc(General_Memory *general, Table *hits, i32 table_size){ - void *mem; - i32 mem_size; - - mem_size = table_required_mem_size(table_size, sizeof(Offset_String)); - if (hits->hash_array == 0){ - mem = general_memory_allocate(general, mem_size); - } - else{ - mem = general_memory_reallocate_nocopy(general, hits->hash_array, mem_size); - } - table_init_memory(hits, mem, table_size, sizeof(Offset_String)); -} - -internal void -search_hits_init(General_Memory *general, Table *hits, String_Space *str, i32 table_size, i32 str_size){ - void *mem; - i32 mem_size; - - if (hits->hash_array == 0){ - search_hits_table_alloc(general, hits, table_size); - } - 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); - table_init_memory(hits, mem, table_size, sizeof(Offset_String)); - } - - if (str->space == 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); - str->max = str_size; - } - - str->pos = str->new_pos = 0; - table_clear(hits); -} - -internal b32 -search_hit_add(General_Memory *general, Table *hits, String_Space *space, char *str, i32 len){ - b32 result; - i32 new_size; - Offset_String ostring; - Table new_hits; - - Assert(len != 0); - - 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); - ostring = strspace_append(space, str, len); - } - - Assert(ostring.size != 0); - - if (table_at_capacity(hits)){ - search_hits_table_alloc(general, &new_hits, hits->max*2); - table_clear(&new_hits); - table_rehash(hits, &new_hits, space->space, tbl_offset_string_hash, tbl_offset_string_compare); - general_memory_free(general, hits->hash_array); - *hits = new_hits; - } - - if (!table_add(hits, &ostring, space->space, tbl_offset_string_hash, tbl_offset_string_compare)){ - result = 1; - strspace_keep_prev(space); - } - else{ - result = 0; - strspace_discard_prev(space); - } - - return(result); -} - -internal Search_Match -search_next_match(Partition *part, Search_Set *set, Search_Iter *iter_){ - Search_Match result = {}; - Search_Iter iter = *iter_; - Search_Range *range; - Temp_Memory temp; - char *spare; - i32 start_pos, end_pos, count; - - temp = begin_temp_memory(part); - spare = push_array(part, char, iter.word.size); - - count = set->count; - for (; iter.i < count;){ - range = set->ranges + iter.i; - - end_pos = range->start + range->size; - - if (iter.pos + iter.word.size < end_pos){ - start_pos = Max(iter.pos, range->start); - result.start = buffer_find_string( - range->buffer, start_pos, end_pos, iter.word.str, iter.word.size, spare); - - if (result.start < end_pos){ - iter.pos = result.start + 1; - if (result.start == 0 || !char_is_alpha_numeric(buffer_get_char(range->buffer, result.start - 1))){ - result.end = buffer_seek_word_right_assume_on_word(range->buffer, result.start); - if (result.end < end_pos){ - result.found_match = 1; - result.buffer = range->buffer; - iter.pos = result.end; - break; - } - } - } - else{ - ++iter.i, iter.pos = 0; - } - } - else{ - ++iter.i, iter.pos = 0; - } - } - end_temp_memory(temp); - - *iter_ = iter; - - return(result); -} - inline void view_change_size(General_Memory *general, View *view){ if (view->file_data.file){ diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index fba80ba8..edf28bb0 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -1069,6 +1069,21 @@ buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width, return(state.cursor); } +internal_4tech Partial_Cursor +buffer_partial_from_pos(Buffer_Type *buffer, int pos){ + Partial_Cursor result = {0}; + + if (pos > buffer->size) pos = buffer->size; + if (pos < 0) pos = 0; + + int line_index = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count); + result.pos = pos; + result.line = line_index+1; + result.character = pos - buffer->line_starts[line_index] + 1; + + return(result); +} + internal_4tech Full_Cursor buffer_cursor_from_pos(Buffer_Type *buffer, int pos, float *wraps, float max_width, float font_height, float *advance_data){ @@ -1086,20 +1101,45 @@ buffer_cursor_from_pos(Buffer_Type *buffer, int pos, float *wraps, return(result); } +internal_4tech Partial_Cursor +buffer_partial_from_line_character(Buffer_Type *buffer, int line, int character){ + Partial_Cursor result = {0}; + + int line_index = line - 1; + if (line_index >= buffer->line_count) line_index = buffer->line_count - 1; + if (line_index < 0) line_index = 0; + + int this_start = buffer->line_starts[line_index]; + int next_start = buffer->size; + if (line_index+1 < buffer->line_count){ + next_start = buffer->line_starts[line_index+1]; + } + + int max_character = (next_start-this_start); + + if (character <= 0) character = 1; + if (character > max_character) character = max_character; + + result.pos = this_start + character - 1; + result.line = line_index+1; + result.character = character; + + return(result); +} + internal_4tech Full_Cursor buffer_cursor_from_line_character(Buffer_Type *buffer, int line, int character, float *wraps, float max_width, float font_height, float *advance_data){ - Full_Cursor result; - int line_index; - - line_index = line - 1; + Full_Cursor result = {0}; + + int line_index = line - 1; if (line_index >= buffer->line_count) line_index = buffer->line_count - 1; if (line_index < 0) line_index = 0; - + result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height); result = buffer_cursor_seek(buffer, seek_line_char(line, character), max_width, font_height, advance_data, result); - + return(result); } diff --git a/power/4coder_experiments.cpp b/power/4coder_experiments.cpp index f6a86390..99f09cf0 100644 --- a/power/4coder_experiments.cpp +++ b/power/4coder_experiments.cpp @@ -238,17 +238,12 @@ get_bindings(void *data, int size){ default_keys(context); - // NOTE(allen|4.0.6): Command maps can be opened more than + // NOTE(allen|a4.0.6): Command maps can be opened more than // once so that you can extend existing maps very easily. // You can also use the helper "restart_map" instead of // begin_map to clear everything that was in the map and // bind new things instead. begin_map(context, mapid_global); - bind(context, '.', MDFR_ALT, change_to_build_panel); - bind(context, ',', MDFR_ALT, close_build_panel); - bind(context, 'n', MDFR_ALT, goto_next_error); - bind(context, 'N', MDFR_ALT, goto_prev_error); - bind(context, 'M', MDFR_ALT, goto_first_error); end_map(context); begin_map(context, mapid_file);