Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/woip/c/livesearch.c
diff options
context:
space:
mode:
Diffstat (limited to 'woip/c/livesearch.c')
-rw-r--r--woip/c/livesearch.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/woip/c/livesearch.c b/woip/c/livesearch.c
new file mode 100644
index 0000000..40028f1
--- /dev/null
+++ b/woip/c/livesearch.c
@@ -0,0 +1,258 @@
+#include <ncurses.h>
+#include <sys/time.h>
+#include "lsearcher.h"
+#include "safe.h"
+#include "wp.h"
+
+#define MAXRES 40
+#define MAXSTR 1024
+
+char needle[MAXSTR];
+char results[MAXRES][MAXSTR];
+uint32_t blocks[MAXRES];
+int nresults;
+
+char *article_file_str;
+int article_pos;
+int pos = 0;
+void (*handler)(int c);
+
+time_t last_sec = 0;
+suseconds_t last_usec = 0;
+
+wp_dump dump = {0};
+
+void search_handler(int c);
+void article_handler(int c);
+void draw_results();
+void maybe_draw_results();
+void handle_finish();
+
+bool handle_result(char *s) {
+ char buf[MAXSTR] = {0};
+ strcpy(buf, s);
+ char *blockpos = strrchr(buf, ' ');
+ int c;
+
+ if(blockpos) {
+ *(blockpos - 1) = '\0';
+ blockpos++;
+
+ blocks[nresults] = atoi(blockpos);
+ strncpy(results[nresults++], buf, MAXSTR);
+
+ maybe_draw_results();
+ } else fatal("invalid: '%s'", buf);
+
+ if((c = getch()) != ERR) {
+ ungetch(c);
+ return false;
+ } else if (nresults >= MAXRES) {
+ handle_finish();
+ return false;
+ } else
+ return true;
+}
+
+void handle_finish() {
+ nodelay(stdscr, FALSE);
+}
+
+void draw_results() {
+ int i = 0, j = 0;
+ char block[20], index[20];
+
+ for(; i < nresults; i++) {
+ move(i + 2, j);
+ j += sprintf(index, "%c ", i == article_pos ? '*' : ' ');
+ j += sprintf(index + j, "%6d", i + 1);
+ addstr(index);
+
+ move(i + 2, j + 1);
+
+ if(i == article_pos)
+ attron(A_UNDERLINE);
+
+ addstr(results[i]);
+
+ if(i == article_pos)
+ attroff(A_UNDERLINE);
+
+ move(i + 2, 60);
+ sprintf(block, "%d", blocks[i]);
+ addstr(block);
+
+ j = 0;
+ }
+}
+
+void search_redraw() {
+ clear();
+ move(0, 0);
+ needle[pos] = '\0';
+ addstr(needle);
+
+ draw_results();
+
+ refresh();
+}
+
+void maybe_draw_results() {
+ struct timeval t;
+ gettimeofday(&t, NULL);
+
+ if(t.tv_sec > last_sec || t.tv_usec > last_usec + 100)
+ search_redraw();
+
+ last_sec = t.tv_sec;
+ last_usec = t.tv_usec;
+}
+
+void research() {
+ nresults = 0;
+ nodelay(stdscr, TRUE);
+ search(&dump.index, needle, handle_result, handle_finish, true, true);
+}
+
+void draw_article() {
+ size_t asize = BZ_MAX_BLOCK;
+ int len;
+ char *start = NULL;
+ char tbuf[60];
+ wp_article article;
+
+ init_article(&article);
+
+ len = block_load_article(&dump, results[article_pos], blocks[article_pos], &article);
+
+ if(len < 0) {
+ move(1, 0);
+ addstr("There was an error retrieving this article");
+ refresh();
+ return;
+ }
+
+ clear();
+
+ move(1, 0);
+ attron(A_UNDERLINE);
+ addstr(results[article_pos]);
+ attroff(A_UNDERLINE);
+
+ move(2, 0);
+ addnstr(article.text, len);
+
+ move(LINES - 2, 0);
+ hline(0, COLS);
+
+ move(LINES - 1, 0);
+ clrtoeol();
+ sprintf(tbuf, "Block %d (%d bytes)", blocks[article_pos], len);
+ addstr(tbuf);
+
+ sprintf(tbuf, "%59s", article_file_str);
+ move(LINES - 1, COLS - 59);
+ addstr(tbuf);
+
+ refresh();
+}
+
+void article_handler(int c) {
+ switch(c) {
+ case KEY_ENTER:
+ case 13:
+ handle_finish();
+ handler = search_handler;
+ search_redraw();
+ return;
+ }
+}
+
+void search_handler(int c) {
+ switch(c) {
+ case KEY_BACKSPACE:
+ case 127:
+ if(pos > 0) {
+ pos--;
+ article_pos = 0;
+ research();
+ }
+ break;
+ case KEY_DOWN:
+ if(article_pos + 1 < nresults) article_pos++;
+ break;
+ case KEY_UP:
+ if(article_pos > 0) article_pos--;
+ break;
+ case KEY_ENTER:
+ case 13:
+ if(nresults > 0) {
+ draw_article();
+ handler = article_handler;
+ return;
+ }
+ break;
+ default:
+ article_pos = 0;
+ needle[pos++] = c;
+ research();
+ }
+
+ search_redraw();
+}
+
+void curses_loop() {
+ initscr();
+ cbreak();
+ noecho();
+ keypad(stdscr, TRUE);
+ nonl();
+ intrflush(stdscr, FALSE);
+
+ while(true) {
+ int c = getch();
+ if(c != ERR) handler(c);
+ }
+}
+
+void reader_loop() {
+ debug("reader_loop");
+
+ wp_article a;
+ char line[MAXSTR];
+
+ init_article(&a);
+
+ while(fgets(line, MAXSTR, stdin)) {
+ line[strlen(line) - 1] = '\0';
+ debug("retrieving %s", line);
+ load_article(&dump, line, &a);
+ if(a.block)
+ puts(a.text);
+ else
+ printf("Couldn't retrieve %s", line);
+ }
+}
+
+int main(int argc, char **argv) {
+ bool noCurses = false;
+ char *slash = strrchr(argv[0], '/');
+
+ debug = true;
+
+ if(!strcmp(slash ? slash + 1 : argv[0], "reader"))
+ noCurses = true;
+
+ load_dump(&dump, argv[1], argv[2], argv[3], argv[4]);
+ article_file_str = argv[1];
+
+ if(!noCurses) {
+ handler = search_handler;
+ curses_loop();
+ } else {
+ debug("calling reader_loop");
+ reader_loop();
+ }
+
+ return 0;
+}