2017-01-29 00:03:23 +00:00
|
|
|
/*
|
|
|
|
* Miscellaneous helpers for common operations.
|
|
|
|
*/
|
|
|
|
|
2018-05-10 03:55:00 +00:00
|
|
|
// TOP
|
|
|
|
|
2017-01-29 00:03:23 +00:00
|
|
|
#if !defined(FCODER_HELPER_H)
|
|
|
|
#define FCODER_HELPER_H
|
|
|
|
|
2018-05-07 02:47:22 +00:00
|
|
|
#define dll_remove(n) (n)->next->prev=(n)->prev,(n)->prev->next=(n)->next
|
|
|
|
|
|
|
|
#define zdll_push_back_(f,l,n) if(f==0){n->next=n->prev=0;f=l=n;}else{n->prev=l;n->next=0;l->next=n;l=n;}
|
|
|
|
#define zdll_push_back(f,l,n) do{ zdll_push_back_((f),(l),(n)) }while(0)
|
|
|
|
#define zdll_remove_front_(f,l,n) if(f==l){f=l=0;}else{f=f->next;f->prev=0;}
|
|
|
|
#define zdll_remove_back_(f,l,n) if(f==l){f=l=0;}else{l=l->prev;l->next=0;}
|
|
|
|
#define zdll_remove_(f,l,n) if(f==n){zdll_remove_front_(f,l,n);}else if(l==n){zdll_remove_back_(f,l,n);}else{dll_remove(n);}
|
|
|
|
#define zdll_remove(f,l,n) do{ zdll_remove_((f),(l),(n)) }while(0)
|
|
|
|
|
2018-05-07 04:44:03 +00:00
|
|
|
#if !defined(Member)
|
|
|
|
# define Member(S,m) (((S*)0)->m)
|
|
|
|
#endif
|
2018-05-07 02:47:22 +00:00
|
|
|
#define PtrDif(a,b) ((uint8_t*)(a) - (uint8_t*)(b))
|
|
|
|
#define PtrAsInt(a) PtrDif(a,0)
|
|
|
|
#define OffsetOfMember(S,m) PtrAsInt(&Member(S,m))
|
|
|
|
#define CastFromMember(S,m,ptr) (S*)( (uint8_t*)(ptr) - OffsetOfMember(S,m) )
|
|
|
|
|
2018-05-07 04:44:03 +00:00
|
|
|
#if !defined(max_f32)
|
2018-05-07 02:47:22 +00:00
|
|
|
inline float
|
2018-05-07 04:44:03 +00:00
|
|
|
max_f32_proc(void){
|
2018-05-07 02:47:22 +00:00
|
|
|
union{
|
|
|
|
uint32_t x;
|
|
|
|
float f;
|
|
|
|
} c;
|
2018-05-07 04:44:03 +00:00
|
|
|
c.x = 0x7f800000;
|
2018-05-07 02:47:22 +00:00
|
|
|
return(c.f);
|
|
|
|
}
|
|
|
|
|
2018-05-07 04:44:03 +00:00
|
|
|
#define max_f32 max_f32_proc()
|
|
|
|
#endif
|
2018-05-07 02:47:22 +00:00
|
|
|
|
2018-05-09 05:22:33 +00:00
|
|
|
#if !defined(ArrayCount)
|
|
|
|
# define ArrayCount(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
#endif
|
|
|
|
|
2017-01-29 00:03:23 +00:00
|
|
|
#include "4coder_seek_types.h"
|
2017-04-15 21:47:23 +00:00
|
|
|
#include "4coder_lib/4coder_utf8.h"
|
2017-01-29 00:03:23 +00:00
|
|
|
|
|
|
|
struct Buffer_Rect{
|
2017-03-23 19:16:39 +00:00
|
|
|
int32_t char0, line0;
|
|
|
|
int32_t char1, line1;
|
2017-01-29 00:03:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef Swap
|
2017-04-15 21:47:23 +00:00
|
|
|
# define Swap(T,a,b) do{ T t = a; a = b; b = t; } while(0)
|
2017-01-29 00:03:23 +00:00
|
|
|
#endif
|
|
|
|
|
2017-02-24 02:30:29 +00:00
|
|
|
static Buffer_Rect
|
2017-01-29 00:03:23 +00:00
|
|
|
get_rect(View_Summary *view){
|
|
|
|
Buffer_Rect rect = {0};
|
|
|
|
|
|
|
|
rect.char0 = view->mark.character;
|
|
|
|
rect.line0 = view->mark.line;
|
|
|
|
|
|
|
|
rect.char1 = view->cursor.character;
|
|
|
|
rect.line1 = view->cursor.line;
|
|
|
|
|
|
|
|
if (rect.line0 > rect.line1){
|
2017-03-23 19:16:39 +00:00
|
|
|
Swap(int32_t, rect.line0, rect.line1);
|
2017-01-29 00:03:23 +00:00
|
|
|
}
|
|
|
|
if (rect.char0 > rect.char1){
|
2017-03-23 19:16:39 +00:00
|
|
|
Swap(int32_t, rect.char0, rect.char1);
|
2017-01-29 00:03:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return(rect);
|
|
|
|
}
|
|
|
|
|
2017-03-23 19:16:39 +00:00
|
|
|
static i32_Rect
|
2017-01-29 00:03:23 +00:00
|
|
|
get_line_x_rect(View_Summary *view){
|
2017-03-23 19:16:39 +00:00
|
|
|
i32_Rect rect = {0};
|
2017-01-29 00:03:23 +00:00
|
|
|
|
|
|
|
if (view->unwrapped_lines){
|
2017-03-23 19:16:39 +00:00
|
|
|
rect.x0 = (int32_t)view->mark.unwrapped_x;
|
|
|
|
rect.x1 = (int32_t)view->cursor.unwrapped_x;
|
2017-01-29 00:03:23 +00:00
|
|
|
}
|
|
|
|
else{
|
2017-03-23 19:16:39 +00:00
|
|
|
rect.x0 = (int32_t)view->mark.wrapped_x;
|
|
|
|
rect.x1 = (int32_t)view->cursor.wrapped_x;
|
2017-01-29 00:03:23 +00:00
|
|
|
}
|
|
|
|
rect.y0 = view->mark.line;
|
|
|
|
rect.y1 = view->cursor.line;
|
|
|
|
|
|
|
|
if (rect.y0 > rect.y1){
|
2017-03-23 19:15:33 +00:00
|
|
|
Swap(int32_t, rect.y0, rect.y1);
|
2017-01-29 00:03:23 +00:00
|
|
|
}
|
|
|
|
if (rect.x0 > rect.x1){
|
2017-03-23 19:15:33 +00:00
|
|
|
Swap(int32_t, rect.x0, rect.x1);
|
2017-01-29 00:03:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return(rect);
|
|
|
|
}
|
|
|
|
|
2017-03-29 16:32:06 +00:00
|
|
|
static View_Summary
|
|
|
|
get_first_view_with_buffer(Application_Links *app, int32_t buffer_id){
|
|
|
|
View_Summary result = {0};
|
|
|
|
View_Summary test = {0};
|
|
|
|
|
|
|
|
if (buffer_id != 0){
|
|
|
|
uint32_t access = AccessAll;
|
|
|
|
for(test = get_view_first(app, access);
|
|
|
|
test.exists;
|
|
|
|
get_view_next(app, &test, access)){
|
|
|
|
|
|
|
|
Buffer_Summary buffer = get_buffer(app, test.buffer_id, access);
|
|
|
|
|
|
|
|
if(buffer.buffer_id == buffer_id){
|
|
|
|
result = test;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2017-02-06 13:49:00 +00:00
|
|
|
static bool32
|
|
|
|
open_file(Application_Links *app, Buffer_Summary *buffer_out, char *filename, int32_t filename_len, bool32 background, bool32 never_new){
|
|
|
|
bool32 result = false;
|
2017-01-29 00:03:23 +00:00
|
|
|
Buffer_Summary buffer = get_buffer_by_name(app, filename, filename_len, AccessProtected|AccessHidden);
|
|
|
|
|
|
|
|
if (buffer.exists){
|
2017-03-29 16:32:06 +00:00
|
|
|
if (buffer_out){
|
|
|
|
*buffer_out = buffer;
|
|
|
|
}
|
2017-01-29 00:03:23 +00:00
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
Buffer_Create_Flag flags = 0;
|
|
|
|
if (background){
|
|
|
|
flags |= BufferCreate_Background;
|
|
|
|
}
|
|
|
|
if (never_new){
|
|
|
|
flags |= BufferCreate_NeverNew;
|
|
|
|
}
|
|
|
|
buffer = create_buffer(app, filename, filename_len, flags);
|
|
|
|
if (buffer.exists){
|
2017-03-29 16:32:06 +00:00
|
|
|
if (buffer_out){
|
|
|
|
*buffer_out = buffer;
|
|
|
|
}
|
2017-01-29 00:03:23 +00:00
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2017-06-28 15:15:54 +00:00
|
|
|
static Buffer_ID
|
|
|
|
buffer_identifier_to_id(Application_Links *app, Buffer_Identifier identifier){
|
|
|
|
Buffer_ID id = 0;
|
|
|
|
if (identifier.id != 0){
|
|
|
|
id = identifier.id;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
Buffer_Summary buffer = get_buffer_by_name(app, identifier.name, identifier.name_len, AccessAll);
|
|
|
|
id = buffer.buffer_id;
|
|
|
|
if (id == 0){
|
|
|
|
buffer = get_buffer_by_file_name(app, identifier.name, identifier.name_len, AccessAll);
|
|
|
|
id = buffer.buffer_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(id);
|
|
|
|
}
|
|
|
|
|
2017-03-29 16:32:06 +00:00
|
|
|
static bool32
|
|
|
|
view_open_file(Application_Links *app, View_Summary *view, char *filename, int32_t filename_len, bool32 never_new){
|
|
|
|
bool32 result = false;
|
2017-01-29 00:03:23 +00:00
|
|
|
|
2017-03-29 16:32:06 +00:00
|
|
|
if (view != 0){
|
2017-01-29 00:03:23 +00:00
|
|
|
Buffer_Summary buffer = {0};
|
|
|
|
if (open_file(app, &buffer, filename, filename_len, false, never_new)){
|
|
|
|
view_set_buffer(app, view, buffer.buffer_id, 0);
|
2017-03-29 16:32:06 +00:00
|
|
|
result = true;
|
2017-01-29 00:03:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2017-02-12 23:04:50 +00:00
|
|
|
static void
|
|
|
|
get_view_prev(Application_Links *app, View_Summary *view, uint32_t access){
|
|
|
|
if (view->exists){
|
|
|
|
View_ID original_id = view->view_id;
|
|
|
|
View_ID check_id = original_id;
|
|
|
|
|
|
|
|
View_Summary new_view = {0};
|
|
|
|
|
|
|
|
for (;;){
|
|
|
|
--check_id;
|
|
|
|
if (check_id <= 0){
|
|
|
|
check_id = 16;
|
|
|
|
}
|
|
|
|
if (check_id == original_id){
|
|
|
|
new_view = *view;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
new_view = get_view(app, check_id, access);
|
|
|
|
if (new_view.exists){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*view = new_view;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static View_Summary
|
|
|
|
get_view_last(Application_Links *app, uint32_t access){
|
|
|
|
View_Summary view = {0};
|
|
|
|
view.exists = true;
|
|
|
|
get_view_prev(app, &view, access);
|
|
|
|
if (view.view_id < 1 || view.view_id > 16){
|
|
|
|
view = null_view_summary;
|
|
|
|
}
|
|
|
|
return(view);
|
|
|
|
}
|
|
|
|
|
2017-01-29 00:03:23 +00:00
|
|
|
static void
|
|
|
|
get_view_next_looped(Application_Links *app, View_Summary *view, uint32_t access){
|
|
|
|
get_view_next(app, view, access);
|
|
|
|
if (!view->exists){
|
|
|
|
*view = get_view_first(app, access);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-12 23:04:50 +00:00
|
|
|
static void
|
|
|
|
get_view_prev_looped(Application_Links *app, View_Summary *view, uint32_t access){
|
|
|
|
get_view_prev(app, view, access);
|
|
|
|
if (!view->exists){
|
|
|
|
*view = get_view_last(app, access);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-29 00:03:23 +00:00
|
|
|
static void
|
|
|
|
refresh_buffer(Application_Links *app, Buffer_Summary *buffer){
|
|
|
|
*buffer = get_buffer(app, buffer->buffer_id, AccessAll);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
refresh_view(Application_Links *app, View_Summary *view){
|
|
|
|
*view = get_view(app, view->view_id, AccessAll);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2018-05-10 03:55:00 +00:00
|
|
|
|
|
|
|
// BOTTOM
|