// * 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);
}
-
}
//---------------------------------------------------------
{
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);
}
}
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)
{
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);
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);
}
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);
}
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);
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);
{
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);
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));
}
}
-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))
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);
}
// 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);
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));
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);
// 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);
// 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);
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);
//---------------------------------------------------------
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;
}
-