From: Mike Lowis Date: Fri, 3 Oct 2025 19:15:00 +0000 (-0400) Subject: added regex searching X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=5e6b5b05945122d7ee2eda0386f732690077aaec;p=proto%2Faos.git added regex searching --- diff --git a/bin/editor.c b/bin/editor.c index 2097a21..7fd649b 100644 --- a/bin/editor.c +++ b/bin/editor.c @@ -5,96 +5,98 @@ // * implement command language // * implement editing shortcuts -typedef struct EditItem { - struct EditItem* next; /* pointer to next operation in the stack */ +typedef struct EditItem +{ + struct EditItem *next; /* pointer to next operation in the stack */ gint beg; /* beginning of affected region */ gint end; /* end of affected region*/ - gchar* data; /* pointer to deleted character data */ + gchar *data; /* pointer to deleted character data */ gint transid; /* id of transaction this item is a part of */ } EditItem; -typedef struct { - char* path; - GtkApplication* app; - GtkWidget* window; - GtkWidget* text_view; - GtkTextBuffer* buffer; - GtkEntry* cmd_entry; - GtkToolItem* save_icon; - GtkToolItem* save_as_icon; - GtkToolItem* undo_icon; - GtkToolItem* redo_icon; - EditItem* undo; - EditItem* redo; +typedef struct +{ + char *path; + GtkApplication *app; + GtkWidget *window; + GtkWidget *text_view; + GtkTextBuffer *buffer; + GtkEntry *cmd_entry; + GtkToolItem *save_icon; + GtkToolItem *save_as_icon; + GtkToolItem *undo_icon; + GtkToolItem *redo_icon; + EditItem *undo; + EditItem *redo; bool edit_in_progress; + GtkTextTag *highlight_tag; } WindowContext; #ifdef __APPLE__ - #define MOD_MASK GDK_META_MASK - #define DEFAULT_FONT "18pt Monaco" +#define MOD_MASK GDK_META_MASK +#define DEFAULT_FONT "18pt Monaco" #else - #define MOD_MASK GDK_CONTROL_MASK - #define DEFAULT_FONT "14pt Liberation Mono" +#define MOD_MASK GDK_CONTROL_MASK +#define DEFAULT_FONT "14pt Liberation Mono" #endif -static void CreateWindow(GtkApplication *app, char* path); +static void CreateWindow(GtkApplication *app, char *path); //--------------------------------------------------------- // Edit Helper Routines //--------------------------------------------------------- -static void UpdateUndoRedoIcons(WindowContext* ctx) +static void UpdateUndoRedoIcons(WindowContext *ctx) { gtk_widget_set_sensitive(GTK_WIDGET(ctx->save_icon), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(ctx->undo_icon), (ctx->undo != NULL)); gtk_widget_set_sensitive(GTK_WIDGET(ctx->redo_icon), (ctx->redo != NULL)); } -static void ReverseEdit(WindowContext* ctx, EditItem** from, EditItem** to) +static void ReverseEdit(WindowContext *ctx, EditItem **from, EditItem **to) { - EditItem* item = *from; + EditItem *item = *from; if (item) { *from = item->next; - GtkTextIter start, stop; - gtk_text_buffer_get_start_iter(ctx->buffer, &start); - gtk_text_buffer_get_start_iter(ctx->buffer, &stop); - gtk_text_iter_set_offset(&start, item->beg); - gtk_text_iter_set_offset(&stop, item->end); - ctx->edit_in_progress = true; - if (item->data) // If action was a delete - { - gtk_text_buffer_insert(ctx->buffer, &start, item->data, item->end - item->beg); - g_free(item->data); - item->data = NULL; - } - else // it was an insert - { - item->data = (char*)gtk_text_buffer_get_text(ctx->buffer, &start, &stop, FALSE); - gtk_text_buffer_delete(ctx->buffer, &start, &stop); - } - item->next = *to; - *to = item; - ctx->edit_in_progress = false; + GtkTextIter start, stop; + gtk_text_buffer_get_start_iter(ctx->buffer, &start); + gtk_text_buffer_get_start_iter(ctx->buffer, &stop); + gtk_text_iter_set_offset(&start, item->beg); + gtk_text_iter_set_offset(&stop, item->end); + ctx->edit_in_progress = true; + if (item->data) // If action was a delete + { + gtk_text_buffer_insert(ctx->buffer, &start, item->data, item->end - item->beg); + g_free(item->data); + item->data = NULL; + } + else // it was an insert + { + item->data = (char *)gtk_text_buffer_get_text(ctx->buffer, &start, &stop, FALSE); + gtk_text_buffer_delete(ctx->buffer, &start, &stop); + } + item->next = *to; + *to = item; + ctx->edit_in_progress = false; } UpdateUndoRedoIcons(ctx); } -static void ClearEdits(EditItem** edits) +static void ClearEdits(EditItem **edits) { - EditItem* curr = *edits; + EditItem *curr = *edits; *edits = NULL; while (curr) { if (curr->data) - { - g_free(curr->data); - } - EditItem* dead = curr; - curr = dead->next; - g_free(dead); + { + g_free(curr->data); + } + EditItem *dead = curr; + curr = dead->next; + g_free(dead); } - } //--------------------------------------------------------- @@ -105,7 +107,7 @@ static void OnOpenApp(GtkApplication *app, GFile **files, gint n_files, gpointer { for (int i = 0; i < n_files; i++) { - char* path = g_file_get_path(files[i]); + char *path = g_file_get_path(files[i]); CreateWindow(app, path); } } @@ -117,33 +119,33 @@ static void OnActivateApp(GtkApplication *app, gpointer user_data) static void OnNew(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; CreateWindow(ctx->app, NULL); } static void OnOpen(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; - GtkWidget* dialog = gtk_file_chooser_dialog_new ( - "Open File", GTK_WINDOW(ctx->window), GTK_FILE_CHOOSER_ACTION_OPEN, - "_Cancel", GTK_RESPONSE_CANCEL, - "_Open", GTK_RESPONSE_ACCEPT, - NULL); - gint res = gtk_dialog_run (GTK_DIALOG (dialog)); + WindowContext *ctx = (WindowContext *)user_data; + GtkWidget *dialog = gtk_file_chooser_dialog_new( + "Open File", GTK_WINDOW(ctx->window), GTK_FILE_CHOOSER_ACTION_OPEN, + "_Cancel", GTK_RESPONSE_CANCEL, + "_Open", GTK_RESPONSE_ACCEPT, + NULL); + gint res = gtk_dialog_run(GTK_DIALOG(dialog)); if (res == GTK_RESPONSE_ACCEPT) { - GtkFileChooser* chooser = GTK_FILE_CHOOSER (dialog); - char* path = gtk_file_chooser_get_filename (chooser); + GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog); + char *path = gtk_file_chooser_get_filename(chooser); CreateWindow(ctx->app, path); } - gtk_widget_destroy (dialog); + gtk_widget_destroy(dialog); } static void OnSaveAs(GtkApplication *app, gpointer user_data); static void OnSave(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; if (ctx->path == NULL) { @@ -158,7 +160,7 @@ static void OnSave(GtkApplication *app, gpointer user_data) char *text = gtk_text_buffer_get_text(ctx->buffer, &start, &end, FALSE); // Save the text to a file - FILE* file = fopen(ctx->path, "w"); + FILE *file = fopen(ctx->path, "w"); if (file) { fputs(text, file); @@ -173,32 +175,32 @@ static void OnSave(GtkApplication *app, gpointer user_data) static void OnSaveAs(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; - GtkWidget* dialog = gtk_file_chooser_dialog_new ( - "Save File As", GTK_WINDOW(ctx->window), GTK_FILE_CHOOSER_ACTION_SAVE, - "_Cancel", GTK_RESPONSE_CANCEL, - "_Save As", GTK_RESPONSE_ACCEPT, - NULL); - gint res = gtk_dialog_run (GTK_DIALOG (dialog)); + WindowContext *ctx = (WindowContext *)user_data; + GtkWidget *dialog = gtk_file_chooser_dialog_new( + "Save File As", GTK_WINDOW(ctx->window), GTK_FILE_CHOOSER_ACTION_SAVE, + "_Cancel", GTK_RESPONSE_CANCEL, + "_Save As", GTK_RESPONSE_ACCEPT, + NULL); + gint res = gtk_dialog_run(GTK_DIALOG(dialog)); if (res == GTK_RESPONSE_ACCEPT) { - GtkFileChooser* chooser = GTK_FILE_CHOOSER (dialog); - ctx->path = gtk_file_chooser_get_filename (chooser); - gtk_window_set_title(GTK_WINDOW(ctx->window), ctx->path); - OnSave(app, user_data); + GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog); + ctx->path = gtk_file_chooser_get_filename(chooser); + gtk_window_set_title(GTK_WINDOW(ctx->window), ctx->path); + OnSave(app, user_data); } - gtk_widget_destroy (dialog); + gtk_widget_destroy(dialog); } static void OnUndo(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; ReverseEdit(ctx, &ctx->undo, &ctx->redo); } static void OnRedo(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; ReverseEdit(ctx, &ctx->redo, &ctx->undo); } @@ -214,15 +216,104 @@ static void OnHelp(GtkApplication *app, gpointer user_data) static void OnCmdChanged(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; - GtkEntryBuffer* buffer = gtk_entry_get_buffer(ctx->cmd_entry); - char *text = (char*)gtk_entry_buffer_get_text(buffer); - printf("cmd: '%s'\n", text); + WindowContext *ctx = (WindowContext *)user_data; + GtkEntryBuffer *buffer = gtk_entry_get_buffer(ctx->cmd_entry); + char *pattern = (char *)gtk_entry_buffer_get_text(buffer); + + // Remove all previous highlights + GtkTextIter start, end; + gtk_text_buffer_get_start_iter(ctx->buffer, &start); + gtk_text_buffer_get_end_iter(ctx->buffer, &end); + gtk_text_buffer_remove_tag(ctx->buffer, ctx->highlight_tag, &start, &end); + + // If search pattern is empty, nothing more to do + if (!pattern || strlen(pattern) == 0) + { + return; + } + + // Get the entire text buffer content + char *buffer_text = gtk_text_buffer_get_text(ctx->buffer, &start, &end, FALSE); + if (!buffer_text) + { + return; + } + + // Compile the regex pattern + GError *error = NULL; + GRegex *regex = g_regex_new(pattern, 0, 0, &error); + + if (!regex) + { + // If regex compilation fails, fall back to literal text search + g_clear_error(&error); + GtkTextIter search_start, match_start, match_end; + gboolean first_match = TRUE; + gtk_text_buffer_get_start_iter(ctx->buffer, &search_start); + + while (gtk_text_iter_forward_search(&search_start, pattern, + GTK_TEXT_SEARCH_TEXT_ONLY, + &match_start, &match_end, NULL)) + { + gtk_text_buffer_apply_tag(ctx->buffer, ctx->highlight_tag, &match_start, &match_end); + + if (first_match) + { + gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ctx->text_view), &match_start, 0.0, TRUE, 0.5, 0.5); + first_match = FALSE; + } + + search_start = match_end; + } + + g_free(buffer_text); + printf("cmd (literal): '%s'\n", pattern); + return; + } + + // Find all regex matches + GMatchInfo *match_info = NULL; + gboolean first_match = TRUE; + + if (g_regex_match(regex, buffer_text, 0, &match_info)) + { + do + { + gint start_pos, end_pos; + if (g_match_info_fetch_pos(match_info, 0, &start_pos, &end_pos)) + { + // Convert byte positions to text iterators + GtkTextIter match_start, match_end; + gtk_text_buffer_get_iter_at_offset(ctx->buffer, &match_start, start_pos); + gtk_text_buffer_get_iter_at_offset(ctx->buffer, &match_end, end_pos); + + // Apply highlight tag to this match + gtk_text_buffer_apply_tag(ctx->buffer, ctx->highlight_tag, &match_start, &match_end); + + // If this is the first match, scroll to center it in the view + if (first_match) + { + gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ctx->text_view), &match_start, 0.0, TRUE, 0.5, 0.5); + first_match = FALSE; + } + } + } while (g_match_info_next(match_info, NULL)); + } + + // Clean up + if (match_info) + { + g_match_info_free(match_info); + } + g_regex_unref(regex); + g_free(buffer_text); + + printf("cmd (regex): '%s'\n", pattern); } static void OnQuit(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; gtk_window_close(GTK_WINDOW(ctx->window)); g_free(ctx); } @@ -234,9 +325,9 @@ static void OnJoin(GtkApplication *app, gpointer user_data) static void OnSelectLine(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; GtkTextIter start, end; - gtk_text_buffer_get_selection_bounds (ctx->buffer, &start, &end); + gtk_text_buffer_get_selection_bounds(ctx->buffer, &start, &end); gtk_text_iter_set_line_offset(&start, 0); gtk_text_iter_forward_to_line_end(&end); gtk_text_buffer_move_mark_by_name(ctx->buffer, "insert", &start); @@ -265,7 +356,7 @@ static void OnHighlightPrev(GtkApplication *app, gpointer user_data) static void OnNewline(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; if (gtk_widget_has_focus(GTK_WIDGET(ctx->cmd_entry))) { OnExec(app, user_data); @@ -274,12 +365,13 @@ static void OnNewline(GtkApplication *app, gpointer user_data) { GtkTextIter start, end; gtk_text_buffer_get_selection_bounds(ctx->buffer, &start, NULL); - end = start; + end = start; gtk_text_iter_set_line_offset(&start, 0); gtk_text_iter_forward_to_line_end(&end); - char* text = gtk_text_buffer_get_text(ctx->buffer, &start, &end, FALSE); - char* indent_end = text; - for (; *indent_end == ' ' || *indent_end == '\t'; indent_end++); + char *text = gtk_text_buffer_get_text(ctx->buffer, &start, &end, FALSE); + char *indent_end = text; + for (; *indent_end == ' ' || *indent_end == '\t'; indent_end++) + ; *indent_end = '\0'; gtk_text_buffer_delete_selection(ctx->buffer, FALSE, FALSE); gtk_text_buffer_insert_at_cursor(ctx->buffer, "\n", 1); @@ -290,16 +382,16 @@ static void OnNewline(GtkApplication *app, gpointer user_data) static void OnTab(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; if (!gtk_widget_has_focus(GTK_WIDGET(ctx->cmd_entry))) { - gtk_text_buffer_insert_at_cursor(ctx->buffer, " ", 4); + gtk_text_buffer_insert_at_cursor(ctx->buffer, " ", 4); } } static void OnToggleCommand(GtkApplication *app, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; if (gtk_widget_has_focus(GTK_WIDGET(ctx->cmd_entry))) { gtk_widget_grab_focus(GTK_WIDGET(ctx->text_view)); @@ -310,32 +402,32 @@ static void OnToggleCommand(GtkApplication *app, gpointer user_data) } } -struct { +struct +{ int mods; int key; - void (*action)(GtkApplication*, gpointer); + void (*action)(GtkApplication *, gpointer); } Keyboard_Shortcuts[] = { - { MOD_MASK, GDK_KEY_o, OnOpen }, - { MOD_MASK, GDK_KEY_s, OnSave }, - { MOD_MASK, GDK_KEY_q, OnQuit }, - { MOD_MASK, GDK_KEY_z, OnUndo }, - { MOD_MASK, GDK_KEY_y, OnRedo }, - { MOD_MASK, GDK_KEY_j, OnJoin }, - { MOD_MASK, GDK_KEY_l, OnSelectLine }, - { MOD_MASK, GDK_KEY_bracketleft, OnUnindent }, - { MOD_MASK, GDK_KEY_bracketright, OnIndent }, - { MOD_MASK, GDK_KEY_slash, OnToggleComment }, - { MOD_MASK, GDK_KEY_t, OnToggleCommand }, - { 0, GDK_KEY_Escape, OnHighlightPrev }, - { 0, GDK_KEY_Return, OnNewline }, - { 0, GDK_KEY_Tab, OnTab }, - { 0, 0, NULL } -}; + {MOD_MASK, GDK_KEY_o, OnOpen}, + {MOD_MASK, GDK_KEY_s, OnSave}, + {MOD_MASK, GDK_KEY_q, OnQuit}, + {MOD_MASK, GDK_KEY_z, OnUndo}, + {MOD_MASK, GDK_KEY_y, OnRedo}, + {MOD_MASK, GDK_KEY_j, OnJoin}, + {MOD_MASK, GDK_KEY_l, OnSelectLine}, + {MOD_MASK, GDK_KEY_bracketleft, OnUnindent}, + {MOD_MASK, GDK_KEY_bracketright, OnIndent}, + {MOD_MASK, GDK_KEY_slash, OnToggleComment}, + {MOD_MASK, GDK_KEY_t, OnToggleCommand}, + {0, GDK_KEY_Escape, OnHighlightPrev}, + {0, GDK_KEY_Return, OnNewline}, + {0, GDK_KEY_Tab, OnTab}, + {0, 0, NULL}}; static gboolean OnKeyPress(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; - for(int i = 0; Keyboard_Shortcuts[i].action; i++) + WindowContext *ctx = (WindowContext *)user_data; + for (int i = 0; Keyboard_Shortcuts[i].action; i++) { if ((event->keyval == Keyboard_Shortcuts[i].key) && ((event->state & Keyboard_Shortcuts[i].mods) == Keyboard_Shortcuts[i].mods)) @@ -347,65 +439,65 @@ static gboolean OnKeyPress(GtkWidget *widget, GdkEventKey *event, gpointer user_ return FALSE; } -void OnInsert(GtkTextBuffer* self, const GtkTextIter* location, gchar* text, gint len, gpointer user_data) +void OnInsert(GtkTextBuffer *self, const GtkTextIter *location, gchar *text, gint len, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; if (!ctx->edit_in_progress) { gtk_widget_set_sensitive(GTK_WIDGET(ctx->save_icon), TRUE); - gint offset = gtk_text_iter_get_offset(location); - if (ctx->undo && !ctx->undo->data && ctx->undo->end == offset) - { + gint offset = gtk_text_iter_get_offset(location); + if (ctx->undo && !ctx->undo->data && ctx->undo->end == offset) + { ctx->undo->end = offset + len; - } - else - { - EditItem* item = g_malloc0(sizeof(EditItem)); - item->beg = gtk_text_iter_get_offset(location); - item->end = item->beg + strlen((char*)text); + } + else + { + EditItem *item = g_malloc0(sizeof(EditItem)); + item->beg = gtk_text_iter_get_offset(location); + item->end = item->beg + strlen((char *)text); item->next = ctx->undo; ctx->undo = item; - } - ClearEdits(&ctx->redo); + } + ClearEdits(&ctx->redo); } } -void OnDelete(GtkTextBuffer* self, const GtkTextIter* start, const GtkTextIter* end, gpointer user_data) +void OnDelete(GtkTextBuffer *self, const GtkTextIter *start, const GtkTextIter *end, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; if (!ctx->edit_in_progress) { gtk_widget_set_sensitive(GTK_WIDGET(ctx->save_icon), TRUE); gint first = gtk_text_iter_get_offset(start); - gint last = gtk_text_iter_get_offset(end); - - if (ctx->undo && ctx->undo->data && ctx->undo->beg == last) - { - gint size = (last - first) + (ctx->undo->end - ctx->undo->beg); - char* new_data = g_malloc(size + 1); - char* del_data = gtk_text_buffer_get_text(ctx->buffer, start, end, FALSE); - strncpy(new_data, del_data, (last-first)); - strncpy(&new_data[last-first], ctx->undo->data, (ctx->undo->end - ctx->undo->beg)); - new_data[size] = '\0'; - ctx->undo->data = new_data; - ctx->undo->beg = first; - } - else - { - EditItem* item = g_malloc0(sizeof(EditItem)); + gint last = gtk_text_iter_get_offset(end); + + if (ctx->undo && ctx->undo->data && ctx->undo->beg == last) + { + gint size = (last - first) + (ctx->undo->end - ctx->undo->beg); + char *new_data = g_malloc(size + 1); + char *del_data = gtk_text_buffer_get_text(ctx->buffer, start, end, FALSE); + strncpy(new_data, del_data, (last - first)); + strncpy(&new_data[last - first], ctx->undo->data, (ctx->undo->end - ctx->undo->beg)); + new_data[size] = '\0'; + ctx->undo->data = new_data; + ctx->undo->beg = first; + } + else + { + EditItem *item = g_malloc0(sizeof(EditItem)); item->beg = gtk_text_iter_get_offset(start); item->end = gtk_text_iter_get_offset(end); item->data = gtk_text_buffer_get_text(ctx->buffer, start, end, FALSE); item->next = ctx->undo; ctx->undo = item; - } - ClearEdits(&ctx->redo); + } + ClearEdits(&ctx->redo); } } -void OnStopEdit(GtkTextBuffer* self, gpointer user_data) +void OnStopEdit(GtkTextBuffer *self, gpointer user_data) { - WindowContext* ctx = (WindowContext*)user_data; + WindowContext *ctx = (WindowContext *)user_data; UpdateUndoRedoIcons(ctx); } @@ -413,39 +505,39 @@ void OnStopEdit(GtkTextBuffer* self, gpointer user_data) // UI Creation Routines //--------------------------------------------------------- -GtkToolItem* toolbar_add_icon(GtkWidget* toolbar, char* icon_name, char* label) +GtkToolItem *toolbar_add_icon(GtkWidget *toolbar, char *icon_name, char *label) { - GtkWidget* icon = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_SMALL_TOOLBAR); - GtkToolItem* button = gtk_tool_button_new (icon, label); + GtkWidget *icon = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_SMALL_TOOLBAR); + GtkToolItem *button = gtk_tool_button_new(icon, label); gtk_tool_item_set_tooltip_text(button, label); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), button, -1); return button; } -void toolbar_add_separator(GtkWidget* toolbar) +void toolbar_add_separator(GtkWidget *toolbar) { - GtkToolItem* sep = gtk_separator_tool_item_new(); + GtkToolItem *sep = gtk_separator_tool_item_new(); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1); } -GtkEntry* toolbar_add_text_entry(GtkWidget* toolbar) +GtkEntry *toolbar_add_text_entry(GtkWidget *toolbar) { - GtkToolItem* item = gtk_tool_item_new(); - GtkWidget* entry = gtk_entry_new(); + GtkToolItem *item = gtk_tool_item_new(); + GtkWidget *entry = gtk_entry_new(); gtk_tool_item_set_expand(item, TRUE); gtk_container_add(GTK_CONTAINER(item), GTK_WIDGET(entry)); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), -1); return GTK_ENTRY(entry); } -static void CreateWindow(GtkApplication *app, char* path) +static void CreateWindow(GtkApplication *app, char *path) { GtkWidget *vbox; GtkWidget *scrolled_window; GtkWidget *toolbar; // Create the main window - WindowContext* ctx = g_malloc0(sizeof(WindowContext)); + WindowContext *ctx = g_malloc0(sizeof(WindowContext)); ctx->app = app; ctx->path = path; ctx->window = gtk_application_window_new(app); @@ -461,8 +553,8 @@ static void CreateWindow(GtkApplication *app, char* path) toolbar = gtk_toolbar_new(); gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolbar), FALSE); gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); - GtkToolItem* new_icon = toolbar_add_icon(toolbar, "document-new", "New File"); - GtkToolItem* open_icon = toolbar_add_icon(toolbar, "document-open", "Open File"); + GtkToolItem *new_icon = toolbar_add_icon(toolbar, "document-new", "New File"); + GtkToolItem *open_icon = toolbar_add_icon(toolbar, "document-open", "Open File"); ctx->save_icon = toolbar_add_icon(toolbar, "document-save", "Save File"); ctx->save_as_icon = toolbar_add_icon(toolbar, "document-save-as", "Save File As..."); gtk_widget_set_sensitive(GTK_WIDGET(ctx->save_icon), (path == NULL ? TRUE : FALSE)); @@ -471,8 +563,8 @@ static void CreateWindow(GtkApplication *app, char* path) ctx->redo_icon = toolbar_add_icon(toolbar, "edit-redo", "Redo"); toolbar_add_separator(toolbar); ctx->cmd_entry = toolbar_add_text_entry(toolbar); - GtkToolItem* exec_icon = toolbar_add_icon(toolbar, "media-playback-start", "Execute"); - GtkToolItem* help_icon = toolbar_add_icon(toolbar, "dialog-question", "Help"); + GtkToolItem *exec_icon = toolbar_add_icon(toolbar, "media-playback-start", "Execute"); + GtkToolItem *help_icon = toolbar_add_icon(toolbar, "dialog-question", "Help"); // Set default state of the icons gtk_widget_set_sensitive(GTK_WIDGET(ctx->save_icon), FALSE); @@ -482,16 +574,23 @@ static void CreateWindow(GtkApplication *app, char* path) // Create the text view and scrolled window ctx->text_view = gtk_text_view_new(); ctx->buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ctx->text_view)); + + // Create highlight tag for search results + ctx->highlight_tag = gtk_text_buffer_create_tag(ctx->buffer, "highlight", + "background", "yellow", + "foreground", "black", + NULL); + if (path) { - FILE* file = fopen(path, "r"); + FILE *file = fopen(path, "r"); if (file) - { + { // Allocate memory for the file fseek(file, 0, SEEK_END); size_t file_size = ftell(file); fseek(file, 0, SEEK_SET); - char* file_contents = (char *)g_malloc(file_size + 1); + char *file_contents = (char *)g_malloc(file_size + 1); // Read file contents fread(file_contents, 1, file_size, file); @@ -501,21 +600,21 @@ static void CreateWindow(GtkApplication *app, char* path) // Set the text buffer content gtk_text_buffer_set_text(ctx->buffer, file_contents, -1); g_free(file_contents); - } + } } - GtkCssProvider *provider = gtk_css_provider_new (); - gtk_css_provider_load_from_data ( + GtkCssProvider *provider = gtk_css_provider_new(); + gtk_css_provider_load_from_data( provider, "textview { font: " DEFAULT_FONT "; }", -1, NULL); - GtkStyleContext *context = gtk_widget_get_style_context (ctx->text_view); - gtk_style_context_add_provider ( - context, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - gtk_text_view_set_top_margin(GTK_TEXT_VIEW (ctx->text_view), 10); - gtk_text_view_set_bottom_margin(GTK_TEXT_VIEW (ctx->text_view), 10); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW (ctx->text_view), 10); - gtk_text_view_set_right_margin(GTK_TEXT_VIEW (ctx->text_view), 10); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW (ctx->text_view), GTK_WRAP_NONE); - gtk_text_view_set_monospace(GTK_TEXT_VIEW (ctx->text_view), TRUE); + GtkStyleContext *context = gtk_widget_get_style_context(ctx->text_view); + gtk_style_context_add_provider( + context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + gtk_text_view_set_top_margin(GTK_TEXT_VIEW(ctx->text_view), 10); + gtk_text_view_set_bottom_margin(GTK_TEXT_VIEW(ctx->text_view), 10); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(ctx->text_view), 10); + gtk_text_view_set_right_margin(GTK_TEXT_VIEW(ctx->text_view), 10); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(ctx->text_view), GTK_WRAP_NONE); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(ctx->text_view), TRUE); scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(scrolled_window), ctx->text_view); @@ -524,19 +623,19 @@ static void CreateWindow(GtkApplication *app, char* path) gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0); // Add event handlers - g_signal_connect(new_icon, "clicked", G_CALLBACK(OnNew), ctx); - g_signal_connect(open_icon, "clicked", G_CALLBACK(OnOpen), ctx); - g_signal_connect(ctx->save_icon, "clicked", G_CALLBACK(OnSave), ctx); - g_signal_connect(ctx->save_as_icon, "clicked", G_CALLBACK(OnSaveAs), ctx); - g_signal_connect(ctx->undo_icon, "clicked", G_CALLBACK(OnUndo), ctx); - g_signal_connect(ctx->redo_icon, "clicked", G_CALLBACK(OnRedo), ctx); - g_signal_connect(exec_icon, "clicked", G_CALLBACK(OnExec), ctx); - g_signal_connect(help_icon, "clicked", G_CALLBACK(OnHelp), ctx); - g_signal_connect(ctx->buffer, "insert-text", G_CALLBACK(OnInsert), ctx); - g_signal_connect(ctx->buffer, "delete-range", G_CALLBACK(OnDelete), ctx); - g_signal_connect(ctx->buffer, "end-user-action", G_CALLBACK(OnStopEdit), ctx); - g_signal_connect(ctx->cmd_entry, "changed", G_CALLBACK(OnCmdChanged), ctx); - g_signal_connect(ctx->window, "key-press-event", G_CALLBACK(OnKeyPress), ctx); + g_signal_connect(new_icon, "clicked", G_CALLBACK(OnNew), ctx); + g_signal_connect(open_icon, "clicked", G_CALLBACK(OnOpen), ctx); + g_signal_connect(ctx->save_icon, "clicked", G_CALLBACK(OnSave), ctx); + g_signal_connect(ctx->save_as_icon, "clicked", G_CALLBACK(OnSaveAs), ctx); + g_signal_connect(ctx->undo_icon, "clicked", G_CALLBACK(OnUndo), ctx); + g_signal_connect(ctx->redo_icon, "clicked", G_CALLBACK(OnRedo), ctx); + g_signal_connect(exec_icon, "clicked", G_CALLBACK(OnExec), ctx); + g_signal_connect(help_icon, "clicked", G_CALLBACK(OnHelp), ctx); + g_signal_connect(ctx->buffer, "insert-text", G_CALLBACK(OnInsert), ctx); + g_signal_connect(ctx->buffer, "delete-range", G_CALLBACK(OnDelete), ctx); + g_signal_connect(ctx->buffer, "end-user-action", G_CALLBACK(OnStopEdit), ctx); + g_signal_connect(ctx->cmd_entry, "changed", G_CALLBACK(OnCmdChanged), ctx); + g_signal_connect(ctx->window, "key-press-event", G_CALLBACK(OnKeyPress), ctx); // Show all the widgets gtk_widget_show_all(ctx->window); @@ -548,11 +647,10 @@ static void CreateWindow(GtkApplication *app, char* path) //--------------------------------------------------------- int main(int argc, char **argv) { - GtkApplication* app = gtk_application_new(NULL, G_APPLICATION_HANDLES_OPEN); + GtkApplication *app = gtk_application_new(NULL, G_APPLICATION_HANDLES_OPEN); g_signal_connect(app, "activate", G_CALLBACK(OnActivateApp), NULL); g_signal_connect(app, "open", G_CALLBACK(OnOpenApp), NULL); int status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); return status; } -