}
void action_find(UiEvent *event, void *data) {
- ui_set_state(event->obj->ctx, APP_STATE_NOTE_FIND);
- ui_unset_state(event->obj->ctx, APP_STATE_NOTE_REPLACE);
+ window_show_searchbar(event->window, FALSE);
}
void action_replace(UiEvent *event, void *data) {
- ui_set_state(event->obj->ctx, APP_STATE_NOTE_FIND);
- ui_set_state(event->obj->ctx, APP_STATE_NOTE_REPLACE);
+ window_show_searchbar(event->window, TRUE);
}
UIWIDGET textview;
UIWIDGET attachments;
+ UIWIDGET searchbar_textfield;
+
/*
* is the note list visible (splitpane child 0)
*/
void note_update_title(NotebookModel *notebook, Note *note) {
NoteModel *m = note->model;
- int index = notebookmode_get_note_index(notebook, note);
+ int index = notebookmodel_get_note_index(notebook, note);
if(index < 0 && !m->new_note) {
return;
}
}
return NULL;
}
+
+
+/* ----------------------------- Search/Replace ---------------------------- */
+
+cxstring text_search_strcasestr(cxstring haystack, cxstring needle) {
+ if(needle.length == 0) {
+ return haystack;
+ }
+
+ for(size_t i=0;i<haystack.length;i++) {
+ cxstring str = cx_strn(haystack.ptr+i, haystack.length-i);
+ cxstring str2 = str;
+ if(str2.length > needle.length) {
+ str2.length = needle.length;
+ }
+ if(!cx_strcasecmp(str2, needle)) {
+ return str;
+ }
+ }
+ return (cxstring){NULL,0};
+}
+
+int text_search(
+ cxstring text,
+ cxstring search,
+ int pos,
+ bool backwards,
+ bool case_sensitive,
+ bool regex,
+ int *result_begin,
+ int *result_end)
+{
+ cxstring result = (cxstring){NULL,0};
+ if(!backwards) {
+ cxstring subtext = cx_strsubs(text, pos);
+ if(!regex) {
+ result = case_sensitive ? cx_strstr(subtext, search) : text_search_strcasestr(subtext, search);
+ } else {
+ // regex search
+ // TODO
+ }
+ } else {
+ // use text_search in forward-mode as long as result_end < pos
+ int begin, end;
+ int prev_begin = -1;
+ int prev_end = 0;
+ cxstring subtext = text;
+ while(text_search(subtext, search, prev_end, FALSE, case_sensitive, regex, &begin, &end)) {
+ if(end > pos) {
+ break;
+ }
+ prev_begin = begin;
+ prev_end = end;
+ }
+ if(prev_begin >= 0) {
+ result = cx_strn(text.ptr + prev_begin, prev_end-prev_begin);
+ }
+ }
+ if(result.ptr) {
+ *result_begin = (int)(result.ptr - text.ptr);
+ *result_end = *result_begin + search.length;
+ return 1;
+ }
+ return 0;
+}
+
+static int get_search_start_pos(NoteModel *note) {
+ int pos = note->text->position(note->text);
+ int sel_begin, sel_end;
+ note->text->selection(note->text, &sel_begin, &sel_end);
+ if(sel_end >= 0) {
+ pos = sel_end;
+ }
+ return pos;
+}
+
+static void note_search(NoteModel *note, bool backwards) {
+ cxstring searchstr = cx_str(ui_get(note->search));
+ if(searchstr.length == 0) {
+ return;
+ }
+
+ cxstring text = cx_str(ui_get(note->text));
+ int pos = get_search_start_pos(note);
+
+ bool cs = (bool)ui_get(note->search_cs);
+ bool regex = (bool)ui_get(note->search_regex);
+
+ int begin, end;
+ if(text_search(text, searchstr, pos, backwards, regex, cs, &begin, &end)) {
+ note->text->setposition(note->text, end);
+ note->text->setselection(note->text, begin, end);
+ }
+}
+
+void note_search_next(NoteModel *note) {
+ note_search(note, FALSE);
+}
+
+void note_search_prev(NoteModel *note) {
+ note_search(note, TRUE);
+}
+
+void note_replace(NoteModel *note) {
+
+}
Attachment* note_get_attachment(Resource *note, const char *path);
+cxstring text_search_strcasestr(cxstring haystack, cxstring needle);
+
+int text_search(
+ cxstring text,
+ cxstring search,
+ int pos,
+ bool backwards,
+ bool case_sensitive,
+ bool regex,
+ int *result_begin,
+ int *result_end);
+
+void note_search_next(NoteModel *note);
+void note_search_prev(NoteModel *note);
+void note_replace(NoteModel *note);
+
#ifdef __cplusplus
}
#endif
*/
}
-int notebookmode_get_note_index(NotebookModel *model, Note *note) {
+int notebookmodel_get_note_index(NotebookModel *model, Note *note) {
CxList *list = model->notes->data;
size_t index = cxListFind(list, note);
return cxListIndexValid(list, index) ? index : -1;
void notebookmodel_add2navstack(NotebookModel *model);
-int notebookmode_get_note_index(NotebookModel *model, Note *note);
+int notebookmodel_get_note_index(NotebookModel *model, Note *note);
#ifdef __cplusplus
ui_grid(obj, .margin = 4, .columnspacing = 4, .rowspacing = 4, .def_hfill = TRUE, .def_vfill = TRUE, .visibility_states = UI_GROUPS(APP_STATE_NOTE_FIND)) {
ui_rlabel(obj, .label = "Find");
- ui_textfield(obj, .hexpand = TRUE, .onactivate = ui_searchbar_next, .varname = "search");
- ui_button(obj, .label = "Previous");
- ui_button(obj, .label = "Next", .onclick = ui_searchbar_next);
+ wdata->searchbar_textfield = ui_textfield(obj, .hexpand = TRUE, .onactivate = action_searchbar_next, .varname = "search");
+ ui_button(obj, .label = "Previous", .onclick = action_searchbar_prev);
+ ui_button(obj, .label = "Next", .onclick = action_searchbar_next);
ui_checkbox(obj, .label = "Case Sensitive", .varname = "search_cs");
ui_checkbox(obj, .label = "Regex", .varname = "search_regex");
ui_button(obj, .icon = "window-close", .onclick = action_searchbar_close);
update_sublists(window->obj->ctx, window->notebooks);
}
+void window_show_searchbar(MainWindow *window, UiBool replace) {
+ UiContext *ctx = window->obj->ctx;
+ ui_set_state(ctx, APP_STATE_NOTE_FIND);
+ if(replace) {
+ ui_set_state(ctx, APP_STATE_NOTE_REPLACE);
+ } else {
+ ui_unset_state(ctx, APP_STATE_NOTE_REPLACE);
+ }
+ ui_textfield_focus(window->searchbar_textfield);
+}
+
typedef struct NotebookCreatedResult {
MainWindow *window;
ui_unset_state(event->obj->ctx, APP_STATE_NOTE_REPLACE);
}
-void ui_searchbar_next(UiEvent *event, void *userdata) {
+void action_searchbar_next(UiEvent *event, void *userdata) {
NoteModel *note = notemodel_current(event->obj);
- if(!note) {
- return;
- }
-
- cxstring searchstr = cx_str(ui_get(note->search));
- if(searchstr.length == 0) {
- return;
+ if(note) {
+ note_search_next(note);
}
-
- cxstring text = cx_str(ui_get(note->text));
- int pos = note->text->position(note->text);
- cxstring subtext = cx_strsubs(text, pos);
-
- cxstring result = cx_strstr(subtext, searchstr);
- if(result.ptr) {
- size_t result_pos = result.ptr - text.ptr;
- size_t result_end = result_pos + searchstr.length;
- note->text->setposition(note->text, result_end);
- note->text->setselection(note->text, (int)result_pos, (int)result_end);
+}
+
+void action_searchbar_prev(UiEvent *event, void *userdata) {
+ NoteModel *note = notemodel_current(event->obj);
+ if(note) {
+ note_search_prev(note);
}
}
// note store listener funcs
void window_store_groups_updated(NoteStore *store, MainWindow *window);
+void window_show_searchbar(MainWindow *window, UiBool replace);
+
void action_notebook_add(UiEvent *event, void *userdata);
void action_notebook_config(UiEvent *event, void *userdata);
void action_textnote_insertimg(UiEvent *event, void *userdata);
void action_searchbar_close(UiEvent *event, void *userdata);
-void ui_searchbar_next(UiEvent *event, void *userdata);
+void action_searchbar_next(UiEvent *event, void *userdata);
+void action_searchbar_prev(UiEvent *event, void *userdata);