draw_text_layout is in the core of 4coder so you can't rewrite it. You can rewrite layout rules (
4coder_layout_rule.cpp, the default is
layout_unwrapped, to change it use the
HookID_Layout hook) but I don't think that it allows you to do what you want (I never used that so I don't actually know, it might be worth looking into that first).
You might want to parse the buffer and when you read a color escaped sequence add scope managed variables with the position and the color, remove the text (you might need to have use another buffer for that as *compilation* is read only I think) and use the attached information when rendering to add color to the text.
Scope managed variables (scope attachments) are variables attached to a combination of "scopes". For example
buffer_get_managed_scope will return a scope that has the life time of the buffer. If the buffer is closed, the variable attached to it will be freed. You can combined several scopes. For example the error highlight feature combine the *compilation* buffer scope and the target source file for an error to store error positions used for highlighting the line in red. If you close either file, the variable are freed. In you case you only need to use the *compilation* buffer scope (I think). In pseudo code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 |
/* At global scope */
CUSTOM_ID( attachment, name_for_the_array );
/* If a function */
/* Create / write */
Managed_Scope buffer_scope = buffer_get_managed_scope( app, buffer );
Managed_Object handle_to_array = alloc_managed_memory_in_scope( buffer_scope, item_size, item_count );
managed_object_store_data( app, handle_to_array, first_index, count, memory_ptr );
/* We want to give a name to the array, so we create a managed object attached to a name, and store the array handle in it. */
Managed_Object* name_for_the_array_ptr = scope_attachment( app, buffer_scope, name_for_the_array, Managed_Object );
if ( name_for_the_array_ptr != 0 ) {
*name_for_the_array_ptr = handle_to_array;
}
/* Read */
Managed_Scope buffer_scope = buffer_get_managed_scope( app, buffer );
Managed_Object* name_for_the_array_ptr = scope_attachment( app, buffer_scope, name_for_the_array, Managed_Object );
Managed_Object handle_to_array = 0;
if ( name_for_the_array_ptr ) {
handle_to_array = *name_for_the_array_ptr;
}
if ( handle_to_array ) {
managed_object_load_data( app, handle_to_array, first_index, count, memory_ptr );
...
}
|
Here is an article about managed scope, but it was written while the feature was being developed and the actual api is different.
New Features P1: Memory Management Overview. Search for
managed in
4coder's documentation.
If the buffer can be modified by the user after you parsed it, for position you can use the marker api. Marker will be moved by 4coder when a buffer is edited (for example if you mark a line, than add new line above, the marker will stay on the correct line). But there isn't much documentation on that and some function are deprecated in the doc, with no information on how to do otherwise (those functions are still used in 4coder code, but they might be removed in the future).
Here is an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 | /* Declare the name of the attachment */
CUSTOM_ID( attachment, ghost_text_marker );
/*
- Create an array of 2 markers on the buffer managed memory;
- store data in it;
- create or get a scope attachment (scope variable) using a name (ghost_text_marker);
- put the handle to the array in the scope attachment
*/
function void add_ghost_text_marker( Application_Links *app, Buffer_ID buffer, i64 position, i64 size ) {
/* The boolean (lean_right) seems to indicate the behavior of the maker when text is inserted at the marker position.*/
Marker markers[ 2 ] = { position, true, position + size, false };
Managed_Scope buffer_scope = buffer_get_managed_scope( app, buffer );
Managed_Object marker_handle = alloc_buffer_markers_on_buffer( app, buffer, 2, 0 );
managed_object_store_data( app, marker_handle, 0, 2, markers );
Assert( managed_object_get_item_size( app, marker_handle ) == sizeof( Marker ) );
Assert( managed_object_get_item_count( app, marker_handle ) == 2 );
Assert( managed_object_get_type( app, marker_handle ) == ManagedObjectType_Markers );
Managed_Object *marker_handle_ptr = scope_attachment( app, buffer_scope, ghost_text_marker, Managed_Object );
if ( marker_handle_ptr != 0 ) {
*marker_handle_ptr = marker_handle;
}
}
CUSTOM_COMMAND_SIG( clean_ghost_text_marker )
CUSTOM_DOC( "Remove ghost text marker from the current buffer." ) {
Marker markers[ 2 ] = { 0 };
View_ID view = get_active_view( app, 0 );
Buffer_ID buffer = view_get_buffer( app, view, 0 );
Managed_Scope buffer_scope = buffer_get_managed_scope( app, buffer );
Managed_Object *marker_handle_ptr = scope_attachment( app, buffer_scope, ghost_text_marker, Managed_Object );
if ( marker_handle_ptr ) {
Managed_Object marker_handle = *marker_handle_ptr;
if ( marker_handle ) {
managed_object_free( app, marker_handle );
( *marker_handle_ptr ) = 0;
}
}
}
CUSTOM_COMMAND_SIG( clean_ghost_text_marker_all_buffer )
CUSTOM_DOC( "Remove ghost text marker from all buffers." ) {
Buffer_ID buffer = get_buffer_next( app, 0, Access_Always );
while ( buffer ) {
Marker markers[ 2 ] = { 0 };
Managed_Scope buffer_scope = buffer_get_managed_scope( app, buffer );
Managed_Object *marker_handle_ptr = scope_attachment( app, buffer_scope, ghost_text_marker, Managed_Object );
if ( marker_handle_ptr ) {
Managed_Object marker_handle = *marker_handle_ptr;
if ( marker_handle ) {
managed_object_free( app, marker_handle );
( *marker_handle_ptr ) = 0;
}
}
buffer = get_buffer_next( app, buffer, Access_Always );
}
}
function void draw_ghost_text( Application_Links* app, Buffer_ID buffer, View_ID view, Text_Layout_ID text_layout_id ) {
Marker markers[ 2 ] = { 0 };
Managed_Scope buffer_scope = buffer_get_managed_scope( app, buffer );
Managed_Object *marker_handle_ptr = scope_attachment( app, buffer_scope, ghost_text_marker, Managed_Object );
Managed_Object marker_handle = 0;
if ( marker_handle_ptr ) {
marker_handle = *marker_handle_ptr;
}
if ( marker_handle ) {
managed_object_load_data( app, marker_handle, 0, 2, markers );
Range_i64 range = { markers[ 0 ].pos, markers[ 1 ].pos };
i64 position = view_get_cursor_pos( app, view );
if ( position >= markers[ 0 ].pos && position < markers[ 1 ].pos ) {
range.min = position;
}
paint_text_color( app, text_layout_id, range, finalize_color( defcolor_comment, 0 ) );
}
}
|