diff --git a/kilo.c b/kilo.c index f7820a2..96df245 100644 --- a/kilo.c +++ b/kilo.c @@ -70,7 +70,7 @@ struct editorConfig E; void editorSetStatusMessage(const char *fmt, ...); void editorRefreshScreen(); -char *editorPrompt(char *prompt); +char *editorPrompt(char *prompt, void (*callback)(char *, int)); /*** terminal ***/ @@ -203,6 +203,19 @@ int editorRowCxToRx(erow *row, int cx) { return rx; } +int editorRowRxToCx(erow *row, int rx) { + int cur_rx = 0; + int cx; + for (cx=0; cx < row->size; cx++) { + if (row->chars[cx] == '\t') + cur_rx += (KILO_TAB_STOP - 1) - (cur_rx % KILO_TAB_STOP); + cur_rx++; + + if (cur_rx > rx) return cx; + } + return cx; +} + void editorUpdateRow(erow *row) { int tabs = 0; int j; @@ -373,7 +386,7 @@ void editorOpen(char *filename) { void editorSave() { if (E.filename == NULL) { - E.filename = editorPrompt("Save as: %s (ESC to cancel)"); + E.filename = editorPrompt("Save as: %s (ESC to cancel)", NULL); if (E.filename == NULL) { editorSetStatusMessage("Save aborted"); return; @@ -401,6 +414,63 @@ void editorSave() { editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno)); } +/** find **/ + +void editorFindCallback(char *query, int key) { + static int last_match = -1; + static int direction = 1; + + if (key == '\r' || key == '\xb') { + last_match = -1; + direction = 1; + return; + } else if (key == ARROW_RIGHT || key == ARROW_DOWN) { + direction = 1; + } else if (key == ARROW_LEFT || key == ARROW_UP) { + direction = -1; + } else { + last_match = -1; + direction = 1; + } + + if (last_match == -1) direction = 1; + int current = last_match; + + int i; + for (i=0; i < E.numrows; i++) { + current += direction; + if (current == -1) current = E.numrows -1; + else if (current == E.numrows) current = 0; + + erow *row = &E.row[current]; + char *match = strstr(row->render, query); + if (match) { + last_match = current; + E.cy = current; + E.cx = editorRowRxToCx(row, match - row->render); // Substract pointers here + E.rowoff = E.numrows; + break; + } + } +} + +void editorFind() { + int saved_cx = E.cx; + int saved_cy = E.cy; + int saved_coloff = E.coloff; + int saved_rowoff = E.rowoff; + + char *query = editorPrompt("Search: %s (Use ESC/Arrows/Enter)", editorFindCallback); + if (query) { + free(query); + } else { + E.cx = saved_cx; + E.cy = saved_cy; + E.coloff = saved_coloff; + E.rowoff = saved_rowoff; + } +} + /*** append buffer ***/ struct abuf { @@ -539,7 +609,7 @@ void editorSetStatusMessage(const char *fmt, ...) { /*** input ***/ -char *editorPrompt(char *prompt) { +char *editorPrompt(char *prompt, void (*callback)(char *, int)) { size_t bufsize = 128; char *buf = malloc(bufsize); @@ -555,11 +625,13 @@ char *editorPrompt(char *prompt) { if (buflen != 0) buf[--buflen] = '\0'; } else if (c == '\x1b') { editorSetStatusMessage(""); + if (callback) callback(buf, c); free(buf); return NULL; } else if (c == '\r') { if (buflen != 0) { editorSetStatusMessage(""); + if (callback) callback(buf, c); return buf; } } else if (!iscntrl(c) && c < 128) { @@ -570,6 +642,8 @@ char *editorPrompt(char *prompt) { buf[buflen++] = c; buf[buflen] = '\0'; } + + if (callback) callback(buf, c); } } @@ -649,6 +723,10 @@ void editorProcessKeypress() { } break; + case CTRL_KEY('f'): + editorFind(); + break; + case BACKSPACE: case CTRL_KEY('h'): case DEL_KEY: @@ -716,7 +794,7 @@ int main(int argc, char *argv[]) { editorOpen(argv[1]); } - editorSetStatusMessage("HELP: Ctrl-S = save | Ctrl-Q = Quit"); + editorSetStatusMessage("HELP: Ctrl-S = save | Ctrl-Q = Quit | Ctrl-F = find"); while (1) { editorRefreshScreen();