wikilib.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227
  1. /*
  2. * Copyright (c) 2009 Openmoko Inc.
  3. *
  4. * Authors Daniel Mack <daniel@caiaq.de>
  5. * Holger Hans Peter Freyther <zecke@openmoko.org>
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <stdlib.h>
  21. #include <inttypes.h>
  22. #include <wikilib.h>
  23. #include <guilib.h>
  24. #include <glyph.h>
  25. #include <history.h>
  26. #include <wl-keyboard.h>
  27. #include <input.h>
  28. #include <msg.h>
  29. #include <file-io.h>
  30. #include <search.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include <stdio.h>
  34. #include <perf.h>
  35. #include <profile.h>
  36. #include <malloc-simple.h>
  37. #include <bmf.h>
  38. #include <lcd_buf_draw.h>
  39. #include <lcd.h>
  40. #include <tick.h>
  41. #include "delay.h"
  42. #include "search_hash.h"
  43. #include "restricted.h"
  44. #include "wiki_info.h"
  45. #ifndef INCLUDED_FROM_KERNEL
  46. #include "time.h"
  47. #else
  48. #include "samo.h"
  49. #endif
  50. //#include <t_services.h>
  51. //#include <kernel.h>
  52. //#include <wl-time.h>
  53. #define DBG_WL 0
  54. struct pos {
  55. unsigned int x;
  56. unsigned int y;
  57. };
  58. int last_display_mode = 0;
  59. int display_mode = DISPLAY_MODE_INDEX;
  60. static struct keyboard_key * pre_key= NULL;
  61. static unsigned int article_touch_down_handled = 0;
  62. static unsigned int touch_down_on_keyboard = 0;
  63. static unsigned int touch_down_on_list = 0;
  64. static struct pos article_touch_down_pos;
  65. static unsigned int touch_y_last_unreleased = 0;
  66. static unsigned int touch_y_last = 0;
  67. static unsigned long start_move_time = 0;
  68. static unsigned long last_unreleased_time = 0;
  69. int last_index_y_pos;
  70. int enter_touch_y_pos = -1;
  71. int last_history_y_pos;
  72. char * articleBuffer = 0;
  73. int articleLength = 0;
  74. unsigned char * membuffer = 0;
  75. int membuffersize = 0;
  76. int curBufferPos = 0;
  77. unsigned char *article_buf_pointer;
  78. //int is_rendering = 0;
  79. int last_selection = 0;
  80. unsigned long start_search_time, last_delete_time;
  81. int last_article_move_time,touch_y_last_article;
  82. int article_touch_count = 0;
  83. int touch_history = 0;
  84. extern unsigned long time_scroll_article_last;
  85. extern unsigned long time_scroll_article_start;
  86. extern long saved_idx_article;
  87. extern long saved_prev_idx_article;
  88. bool random_press = false;
  89. extern int stop_render_article;
  90. int time_random_last = 0;
  91. extern bool search_string_changed;
  92. extern unsigned int time_search_last;
  93. extern int b_show_scroll_bar;
  94. extern int display_first_page;
  95. bool press_delete_button = false;
  96. extern bool search_string_changed_remove;
  97. int history_touch_pos_y_last;
  98. int touch_search = 0,search_touch_pos_y_last=0;
  99. bool article_moved = false;
  100. int article_scroll_pixel = INITIAL_ARTICLE_SCROLL_THRESHOLD;
  101. int article_moved_pixels = 0;
  102. extern int link_to_be_inverted;
  103. extern int link_currently_inverted;
  104. long finger_move_speed = 0;
  105. #ifdef OVER_SCROLL_ENABLED
  106. extern int over_scroll_lines;
  107. #endif
  108. int finger_touched = 0;
  109. void repaint_search(void)
  110. {
  111. guilib_fb_lock();
  112. search_to_be_reloaded(SEARCH_TO_BE_RELOADED_SET, SEARCH_RELOAD_KEEP_REFRESH);
  113. keyboard_paint();
  114. guilib_fb_unlock();
  115. }
  116. /* this is only called for the index page */
  117. static void toggle_soft_keyboard(void)
  118. {
  119. //guilib_fb_lock();
  120. int mode = keyboard_get_mode();
  121. /* Set the keyboard mode to what we want to change to. */
  122. if (mode == KEYBOARD_NONE || search_result_count()==0) {
  123. keyboard_set_mode(KEYBOARD_CHAR);
  124. if (mode == KEYBOARD_NONE)
  125. restore_search_list_page();
  126. keyboard_paint();
  127. } else {
  128. keyboard_set_mode(KEYBOARD_NONE);
  129. search_to_be_reloaded(SEARCH_TO_BE_RELOADED_SET, SEARCH_RELOAD_KEEP_RESULT);
  130. }
  131. //guilib_fb_unlock();
  132. }
  133. static void print_intro()
  134. {
  135. //keyboard_set_mode(KEYBOARD_CHAR);
  136. guilib_fb_lock();
  137. guilib_clear();
  138. //membuffer = malloc_simple(1024*1024,MEM_TAG_ARTICLE_F1);
  139. keyboard_paint();
  140. guilib_fb_unlock();
  141. }
  142. static unsigned int s_article_y_pos;
  143. static uint32_t s_article_offset = 0;
  144. void invert_selection(int old_pos, int new_pos, int start_pos, int height)
  145. {
  146. guilib_fb_lock();
  147. if (old_pos != -1)
  148. guilib_invert(start_pos - 2 + old_pos * height, height);
  149. if (new_pos != -1)
  150. guilib_invert(start_pos - 2 + new_pos * height, height);
  151. guilib_fb_unlock();
  152. }
  153. void invert_area(int start_x, int start_y, int end_x, int end_y)
  154. {
  155. guilib_fb_lock();
  156. guilib_invert_area(start_x,start_y,end_x,end_y);
  157. guilib_fb_unlock();
  158. }
  159. int article_open(const char *article)
  160. {
  161. DP(DBG_WL, ("O article_open() '%s'\n", article));
  162. s_article_offset = strtoul(article, 0 /* endptr */, 16 /* base */);
  163. s_article_y_pos = 0;
  164. return 0;
  165. }
  166. #if 0
  167. // this is no longer used
  168. void article_display(enum article_nav nav)
  169. {
  170. unsigned int screen_height = guilib_framebuffer_height();
  171. DP(DBG_WL, ("O article_display() %i article_offset %u article_y_pos %u\n", nav, s_article_offset, s_article_y_pos));
  172. if (nav == ARTICLE_PAGE_NEXT)
  173. s_article_y_pos += screen_height;
  174. else if (nav == ARTICLE_PAGE_PREV)
  175. s_article_y_pos = (s_article_y_pos <= screen_height) ? 0 : s_article_y_pos - screen_height;
  176. // wom_draw(g_womh, s_article_offset, framebuffer, s_article_y_pos, screen_height);
  177. }
  178. #endif
  179. #if 0
  180. // this is no longer used
  181. int article_open_pcf(const char *filename)
  182. {
  183. FILE * pFile;
  184. long lSize;
  185. size_t result;
  186. pFile = fopen (filename , "rb" );
  187. if (pFile==NULL)
  188. return -1;
  189. fseek (pFile , 0 , SEEK_END);
  190. lSize = ftell (pFile);
  191. rewind (pFile);
  192. // allocate memory to contain the whole file:
  193. articleBuffer = (char*) malloc (sizeof(char)*lSize);
  194. if (articleBuffer == NULL)
  195. {
  196. fclose(pFile);
  197. return -1;
  198. }
  199. // copy the file into the buffer:
  200. result = fread (articleBuffer,1,lSize,pFile);
  201. if (result != lSize)
  202. {
  203. fclose(pFile);
  204. return -1;
  205. }
  206. // terminate
  207. fclose (pFile);
  208. framebuffer_article=(char*)malloc(guilib_framebuffer_width()*nLine);
  209. memset(framebuffer_article,0,guilib_framebuffer_width()*nLine);
  210. render_article(articleBuffer,articleLength,framebuffer_article);
  211. return lSize;
  212. }
  213. #endif
  214. void article_display_pcf(int yPixel)
  215. {
  216. int pos;
  217. int copysize;
  218. int framebuffersize;
  219. framebuffersize = guilib_framebuffer_size();
  220. pos = curBufferPos+((yPixel*LCD_VRAM_WIDTH_PIXELS)/8);
  221. if(pos<0 || pos>membuffersize)
  222. {
  223. return;
  224. }
  225. copysize = membuffersize-pos;
  226. if(copysize>framebuffersize)
  227. copysize = framebuffersize;
  228. else
  229. {
  230. return;
  231. }
  232. guilib_fb_lock();
  233. guilib_clear();
  234. memcpy(framebuffer,membuffer+pos,copysize);
  235. guilib_fb_unlock();
  236. curBufferPos = pos;
  237. }
  238. static void handle_search_key(char keycode, unsigned long ev_time)
  239. {
  240. int rc = 0;
  241. if (keycode == WL_KEY_NLS) {
  242. #ifdef INCLUDED_FROM_KERNEL
  243. delay_us(100000);
  244. #endif
  245. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_NOW, 0);
  246. display_mode = DISPLAY_MODE_WIKI_SELECTION;
  247. keyboard_set_mode(KEYBOARD_NONE);
  248. wiki_selection();
  249. return;
  250. // } else if (keycode == WL_KEY_BACKSPACE) {
  251. // rc = search_remove_char(0, ev_time);
  252. } else if (is_supported_search_char(keycode)) {
  253. rc = search_add_char(tolower(keycode), ev_time);
  254. } else {
  255. if(keycode == -42) // toggling keyboard will be handled at key down
  256. {
  257. rc = -1;
  258. }
  259. else
  260. {
  261. return;
  262. }
  263. }
  264. guilib_fb_lock();
  265. if (!rc)
  266. search_to_be_reloaded(SEARCH_TO_BE_RELOADED_SET, SEARCH_RELOAD_NO_POPULATE);
  267. //
  268. // keyboard_paint();
  269. guilib_fb_unlock();
  270. }
  271. static void handle_cursor(struct wl_input_event *ev)
  272. {
  273. DP(DBG_WL, ("O handle_cursor()\n"));
  274. if (display_mode == DISPLAY_MODE_ARTICLE) {
  275. if (ev->key_event.keycode == WL_INPUT_KEY_CURSOR_DOWN)
  276. display_article_with_pcf(50);
  277. else if (ev->key_event.keycode == WL_INPUT_KEY_CURSOR_UP)
  278. display_article_with_pcf(-50);
  279. } else if (display_mode == DISPLAY_MODE_INDEX && keyboard_get_mode() == KEYBOARD_NONE) {
  280. if (ev->key_event.keycode == WL_INPUT_KEY_CURSOR_DOWN)
  281. display_article_with_pcf(50);
  282. else if (ev->key_event.keycode == WL_INPUT_KEY_CURSOR_UP)
  283. display_article_with_pcf(-50);
  284. } else if (display_mode == DISPLAY_MODE_HISTORY && keyboard_get_mode() == KEYBOARD_NONE) {
  285. if (ev->key_event.keycode == WL_INPUT_KEY_CURSOR_DOWN)
  286. display_article_with_pcf(50);
  287. else if (ev->key_event.keycode == WL_INPUT_KEY_CURSOR_UP)
  288. display_article_with_pcf(-50);
  289. }
  290. }
  291. extern int restricted_article;
  292. static void handle_key_release(int keycode)
  293. {
  294. // static long idx_article = 0;
  295. static int first_time_random = 0;
  296. int mode;
  297. finger_move_speed = 0;
  298. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_NOW, 0); // reset invert immediately
  299. DP(DBG_WL, ("O handle_key_release()\n"));
  300. mode = keyboard_get_mode();
  301. if (keycode == WL_INPUT_KEY_POWER) {
  302. #ifdef INCLUDED_FROM_KERNEL
  303. if (history_list_save(HISTORY_SAVE_POWER_OFF))
  304. {
  305. delay_us(200000);
  306. }
  307. #endif
  308. } else if (keycode == WL_INPUT_KEY_SEARCH) {
  309. article_buf_pointer = NULL;
  310. /* back to search */
  311. if (display_mode == DISPLAY_MODE_INDEX) {
  312. toggle_soft_keyboard();
  313. } else {
  314. search_set_selection(-1);
  315. display_mode = DISPLAY_MODE_INDEX;
  316. keyboard_set_mode(KEYBOARD_CHAR);
  317. repaint_search();
  318. }
  319. } else if (keycode == WL_INPUT_KEY_HISTORY) {
  320. if (display_mode != DISPLAY_MODE_HISTORY) {
  321. article_buf_pointer = NULL;
  322. history_reload();
  323. display_mode = DISPLAY_MODE_HISTORY;
  324. keyboard_set_mode(KEYBOARD_NONE);
  325. } else {
  326. if (keyboard_get_mode() == KEYBOARD_CLEAR_HISTORY)
  327. {
  328. keyboard_set_mode(KEYBOARD_NONE);
  329. guilib_fb_lock();
  330. //keyboard_paint();
  331. draw_clear_history(1);
  332. guilib_fb_unlock();
  333. } else if (history_get_count() > 0 && display_first_page) {
  334. keyboard_set_mode(KEYBOARD_CLEAR_HISTORY);
  335. guilib_fb_lock();
  336. //keyboard_paint();
  337. draw_clear_history(0);
  338. guilib_fb_unlock();
  339. }
  340. }
  341. } else if (keycode == WL_INPUT_KEY_RANDOM) {
  342. if (first_time_random < 4)
  343. first_time_random++;
  344. if (first_time_random == 3)
  345. {
  346. first_time_random = 4;
  347. if (init_article_filter())
  348. return;
  349. }
  350. article_buf_pointer = NULL;
  351. display_mode = DISPLAY_MODE_ARTICLE;
  352. last_display_mode = DISPLAY_MODE_INDEX;
  353. random_article();
  354. } else if (display_mode == DISPLAY_MODE_INDEX) {
  355. article_buf_pointer = NULL;
  356. if (keycode == WL_KEY_RETURN) {
  357. int cur_selection = search_current_selection();
  358. retrieve_article(cur_selection);
  359. #ifdef PROFILER_ON
  360. } else if (keycode == WL_KEY_HASH) {
  361. /* activate if you want to run performance tests */
  362. /* perf_test(); */
  363. malloc_status_simple();
  364. prof_print();
  365. #endif
  366. } else {
  367. handle_search_key(keycode, get_time_ticks());
  368. }
  369. } else if (display_mode == DISPLAY_MODE_ARTICLE) {
  370. // article_buf_pointer = NULL;
  371. if (keycode == WL_KEY_BACKSPACE) {
  372. if (last_display_mode == DISPLAY_MODE_INDEX) {
  373. display_mode = DISPLAY_MODE_INDEX;
  374. repaint_search();
  375. } else if (last_display_mode == DISPLAY_MODE_HISTORY) {
  376. display_mode = DISPLAY_MODE_HISTORY;
  377. history_reload();
  378. }
  379. }
  380. }
  381. }
  382. static void average_xy(int *average_x, int *average_y, int last_5_x[], int last_5_y[], unsigned long last_5_y_time_ticks[])
  383. {
  384. int i;
  385. int xy_count = 1;
  386. *average_x = last_5_x[0];
  387. *average_y = last_5_y[0];
  388. for (i = 1; i < 5; i++)
  389. {
  390. if (last_5_x[i] >= 0 && time_diff(last_5_y_time_ticks[i], last_5_y_time_ticks[0]) < seconds_to_ticks(LINK_ACTIVATION_TIME_THRESHOLD))
  391. {
  392. xy_count++;
  393. *average_x += last_5_x[i];
  394. *average_y += last_5_y[i];
  395. }
  396. }
  397. *average_x /= xy_count;
  398. *average_y /= xy_count;
  399. }
  400. static void handle_touch(struct wl_input_event *ev)
  401. {
  402. //int offset,offset_count,
  403. int article_link_number=-1;
  404. int enter_touch_y_pos_record;
  405. //int time_diff_search;
  406. int mode;
  407. struct keyboard_key * key;
  408. static int last_5_x[5];
  409. static int last_5_y[5];
  410. static unsigned long last_5_y_time_ticks[5];
  411. int i;
  412. int average_x, average_y;
  413. long time_now;
  414. DP(DBG_WL, ("%s() touch event @%d,%d val %d\n", __func__,
  415. ev->touch_event.x, ev->touch_event.y, ev->touch_event.value));
  416. mode = keyboard_get_mode();
  417. if (display_mode == DISPLAY_MODE_INDEX && (mode == KEYBOARD_CHAR || mode == KEYBOARD_NUM))
  418. {
  419. article_buf_pointer = NULL;
  420. if (!touch_down_on_keyboard && !touch_down_on_list)
  421. {
  422. last_5_x[0] = ev->touch_event.x;
  423. last_5_y[0] = ev->touch_event.y;
  424. last_5_y_time_ticks[0] = ev->touch_event.ticks;
  425. for (i = 1; i < 5; i++)
  426. {
  427. last_5_x[i] = -1;
  428. last_5_y[i] = -1;
  429. }
  430. }
  431. else
  432. {
  433. for (i = 4; i >= 1; i--)
  434. {
  435. last_5_x[i] = last_5_x[i-1];
  436. last_5_y[i] = last_5_y[i-1];
  437. last_5_y_time_ticks[i] = last_5_y_time_ticks[i-1];
  438. }
  439. last_5_x[0] = ev->touch_event.x;
  440. last_5_y[0] = ev->touch_event.y;
  441. last_5_y_time_ticks[0] = ev->touch_event.ticks;
  442. }
  443. average_xy(&average_x, &average_y, last_5_x, last_5_y, last_5_y_time_ticks);
  444. key = keyboard_get_data(average_x, average_y);
  445. if (ev->touch_event.value == 0) {
  446. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_DELAY, ev->touch_event.ticks); // reset invert with delay
  447. enter_touch_y_pos_record = enter_touch_y_pos;
  448. enter_touch_y_pos = -1;
  449. touch_search = 0;
  450. if (pre_key && pre_key != key && keyboard_adjacent_keys(pre_key, key))
  451. {
  452. touch_down_on_keyboard = 0;
  453. touch_down_on_list = 0;
  454. pre_key = NULL;
  455. goto out;
  456. }
  457. pre_key = NULL;
  458. if (press_delete_button)
  459. {
  460. touch_down_on_keyboard = 0;
  461. touch_down_on_list = 0;
  462. press_delete_button = false;
  463. goto out;
  464. }
  465. if (key) {
  466. if (!touch_down_on_keyboard) {
  467. touch_down_on_keyboard = 0;
  468. touch_down_on_list = 0;
  469. goto out;
  470. }
  471. handle_search_key(key->key, ev->touch_event.ticks);
  472. }
  473. else {
  474. if (!touch_down_on_list || ev->touch_event.y < RESULT_START - RESULT_HEIGHT) {
  475. touch_down_on_keyboard = 0;
  476. touch_down_on_list = 0;
  477. goto out;
  478. }
  479. if(search_result_count()==0)
  480. goto out;
  481. //search_set_selection(last_selection);
  482. //search_open_article(last_selection);
  483. if(search_result_selected()>=0)
  484. {
  485. display_mode = DISPLAY_MODE_ARTICLE;
  486. last_display_mode = DISPLAY_MODE_INDEX;
  487. search_open_article(search_result_selected());
  488. }
  489. }
  490. touch_down_on_keyboard = 0;
  491. touch_down_on_list = 0;
  492. } else {
  493. if (pre_key && pre_key->key != key->key && keyboard_adjacent_keys(pre_key, key))
  494. {
  495. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_NOW, 0);
  496. goto out;
  497. }
  498. if(enter_touch_y_pos<0) //record first touch y pos
  499. enter_touch_y_pos = ev->touch_event.y;
  500. last_index_y_pos = ev->touch_event.y;
  501. start_search_time = ev->touch_event.ticks;
  502. last_delete_time = start_search_time;
  503. if (key) {
  504. if(key->key==8)//press "<" button
  505. {
  506. if (!press_delete_button)
  507. {
  508. press_delete_button = true;
  509. if(get_search_string_len()>0)
  510. {
  511. time_now = get_time_ticks();
  512. if (!search_remove_char(0, time_now))
  513. {
  514. search_string_changed_remove = true;
  515. search_to_be_reloaded(SEARCH_TO_BE_RELOADED_SET, SEARCH_RELOAD_NO_POPULATE);
  516. }
  517. last_delete_time = time_now;
  518. }
  519. }
  520. }
  521. else if(key->key == -42)
  522. {
  523. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_NOW, 0);
  524. if (!touch_down_on_keyboard)
  525. {
  526. mode = keyboard_get_mode();
  527. if(mode == KEYBOARD_CHAR)
  528. keyboard_set_mode(KEYBOARD_NUM);
  529. else if(mode == KEYBOARD_NUM)
  530. keyboard_set_mode(KEYBOARD_CHAR);
  531. guilib_fb_lock();
  532. keyboard_paint();
  533. guilib_fb_unlock();
  534. }
  535. }
  536. if (!touch_down_on_keyboard && !touch_down_on_list)
  537. touch_down_on_keyboard = 1;
  538. if (pre_key && pre_key->key == key->key) goto out;
  539. if (touch_down_on_keyboard) {
  540. keyboard_key_invert(key);
  541. if (pre_key && !keyboard_adjacent_keys(pre_key, key))
  542. {
  543. handle_search_key(pre_key->key, ev->touch_event.ticks);
  544. pre_key = NULL;
  545. }
  546. else
  547. pre_key = key;
  548. }
  549. } else {
  550. if (!touch_down_on_keyboard && !touch_down_on_list)
  551. touch_down_on_list = 1;
  552. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_DELAY, ev->touch_event.ticks); // reset invert with delay
  553. pre_key = NULL;
  554. if (!search_result_count()) goto out;
  555. if(touch_search == 0)
  556. {
  557. //last_search_y_pos = ev->touch_event.y;
  558. touch_search = 1;
  559. }
  560. else
  561. {
  562. if(search_result_selected()>=0 && abs(ev->touch_event.y-search_touch_pos_y_last)>5)
  563. {
  564. invert_selection(search_result_selected(),-1, RESULT_START, RESULT_HEIGHT);
  565. search_set_selection(-1);
  566. }
  567. goto out;
  568. }
  569. int new_selection;
  570. if((ev->touch_event.y - RESULT_START)<0)
  571. new_selection = -1;
  572. else
  573. new_selection = ((unsigned int)ev->touch_event.y - RESULT_START) / RESULT_HEIGHT;
  574. if (new_selection == search_result_selected()) goto out;
  575. unsigned int avail_count = keyboard_get_mode() == KEYBOARD_NONE ?
  576. NUMBER_OF_FIRST_PAGE_RESULTS : NUMBER_OF_RESULTS_KEYBOARD;
  577. avail_count = search_result_count() > avail_count ? avail_count : search_result_count();
  578. if (new_selection >= avail_count) goto out;
  579. if (touch_down_on_keyboard) goto out;
  580. //invert_selection(search_result_selected(), new_selection, RESULT_START, RESULT_HEIGHT);
  581. invert_selection(-1, new_selection, RESULT_START, RESULT_HEIGHT);
  582. last_selection = new_selection ;
  583. search_set_selection(new_selection);
  584. search_touch_pos_y_last = ev->touch_event.y;
  585. }
  586. }
  587. }
  588. else if (display_mode == DISPLAY_MODE_HISTORY && mode == KEYBOARD_CLEAR_HISTORY)
  589. {
  590. key = keyboard_get_data(ev->touch_event.x, ev->touch_event.y);
  591. if (ev->touch_event.value == 0) {
  592. #ifdef INCLUDED_FROM_KERNEL
  593. delay_us(100000 * 2);
  594. #endif
  595. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_NOW, 0);
  596. enter_touch_y_pos_record = enter_touch_y_pos;
  597. enter_touch_y_pos = -1;
  598. touch_search = 0;
  599. pre_key = NULL;
  600. if (press_delete_button)
  601. {
  602. press_delete_button = false;
  603. goto out;
  604. }
  605. if (key) {
  606. if (!touch_down_on_keyboard) {
  607. touch_down_on_keyboard = 0;
  608. touch_down_on_list = 0;
  609. goto out;
  610. }
  611. if (key->key == 'Y') {
  612. history_clear();
  613. keyboard_set_mode(KEYBOARD_NONE);
  614. history_reload();
  615. } else if (key->key == 'N') {
  616. keyboard_set_mode(KEYBOARD_NONE);
  617. guilib_fb_lock();
  618. draw_clear_history(1);
  619. guilib_fb_unlock();
  620. }
  621. }
  622. else {
  623. touch_down_on_keyboard = 0;
  624. touch_down_on_list = 0;
  625. goto out;
  626. }
  627. } else {
  628. if(enter_touch_y_pos<0) //record first touch y pos
  629. enter_touch_y_pos = ev->touch_event.y;
  630. last_index_y_pos = ev->touch_event.y;
  631. if (key) {
  632. if (!touch_down_on_keyboard)
  633. touch_down_on_keyboard = 1;
  634. if (pre_key && pre_key->key == key->key) goto out;
  635. if (touch_down_on_keyboard) {
  636. keyboard_key_invert(key);
  637. if (pre_key && !keyboard_adjacent_keys(pre_key, key))
  638. {
  639. handle_search_key(pre_key->key, ev->touch_event.ticks);
  640. pre_key = NULL;
  641. }
  642. else
  643. pre_key = key;
  644. }
  645. } else {
  646. touch_down_on_keyboard = 0;
  647. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_DELAY, ev->touch_event.ticks); // reset invert with delay
  648. pre_key = NULL;
  649. }
  650. }
  651. }
  652. else if (display_mode == DISPLAY_MODE_RESTRICTED)
  653. {
  654. key = keyboard_get_data(ev->touch_event.x, ev->touch_event.y);
  655. if (ev->touch_event.value == 0) {
  656. if (key->key == 'Y' || key->key == 'N' || key->key == 'P')
  657. {
  658. #ifdef INCLUDED_FROM_KERNEL
  659. delay_us(100000 * 2);
  660. #endif
  661. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_NOW, 0);
  662. }
  663. else
  664. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_DELAY, ev->touch_event.ticks); // reset invert with delay
  665. enter_touch_y_pos_record = enter_touch_y_pos;
  666. enter_touch_y_pos = -1;
  667. touch_search = 0;
  668. if (pre_key && pre_key != key && keyboard_adjacent_keys(pre_key, key))
  669. {
  670. touch_down_on_keyboard = 0;
  671. touch_down_on_list = 0;
  672. pre_key = NULL;
  673. goto out;
  674. }
  675. pre_key = NULL;
  676. if (press_delete_button)
  677. {
  678. touch_down_on_keyboard = 0;
  679. touch_down_on_list = 0;
  680. press_delete_button = false;
  681. goto out;
  682. }
  683. if (key) {
  684. if (!touch_down_on_keyboard) {
  685. touch_down_on_keyboard = 0;
  686. goto out;
  687. }
  688. handle_password_key(key->key);
  689. }
  690. touch_down_on_keyboard = 0;
  691. } else {
  692. if (pre_key && pre_key->key != key->key && keyboard_adjacent_keys(pre_key, key))
  693. {
  694. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_NOW, 0);
  695. goto out;
  696. }
  697. if(enter_touch_y_pos<0) //record first touch y pos
  698. enter_touch_y_pos = ev->touch_event.y;
  699. last_index_y_pos = ev->touch_event.y;
  700. start_search_time = ev->touch_event.ticks;
  701. last_delete_time = start_search_time;
  702. if (key) {
  703. if(key->key==8)//press "<" button
  704. {
  705. if (!press_delete_button)
  706. {
  707. press_delete_button = true;
  708. if (get_password_string_len()>0)
  709. {
  710. time_now = get_time_ticks();
  711. password_remove_char();
  712. last_delete_time = time_now;
  713. }
  714. }
  715. }
  716. else if(key->key == -42)
  717. {
  718. mode = keyboard_get_mode();
  719. if(mode == KEYBOARD_PASSWORD_CHAR)
  720. keyboard_set_mode(KEYBOARD_PASSWORD_NUM);
  721. else if(mode == KEYBOARD_PASSWORD_NUM)
  722. keyboard_set_mode(KEYBOARD_PASSWORD_CHAR);
  723. guilib_fb_lock();
  724. keyboard_paint();
  725. guilib_fb_unlock();
  726. }
  727. if (!touch_down_on_keyboard)
  728. touch_down_on_keyboard = 1;
  729. if (pre_key && pre_key->key == key->key) goto out;
  730. if (touch_down_on_keyboard) {
  731. keyboard_key_invert(key);
  732. pre_key = key;
  733. }
  734. } else {
  735. keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_NOW, 0);
  736. pre_key = NULL;
  737. search_touch_pos_y_last = ev->touch_event.y;
  738. }
  739. }
  740. } else {
  741. if (ev->touch_event.value == 0) {
  742. unsigned long diff_ticks = 0;
  743. long diff_y = 0;
  744. finger_touched = 0;
  745. time_scroll_article_last = ev->touch_event.ticks;
  746. for (i = 4; i > 0; i--)
  747. {
  748. if (last_5_y[i] >= 0)
  749. {
  750. diff_y = last_5_y[i] - ev->touch_event.y;
  751. diff_ticks = time_diff(ev->touch_event.ticks, last_5_y_time_ticks[i]);
  752. break;
  753. }
  754. }
  755. if (diff_ticks <= 0 || abs(article_moved_pixels) > SMOOTH_SCROLL_ACTIVATION_OFFSET_HIGH_THRESHOLD ||
  756. abs(article_moved_pixels) < SMOOTH_SCROLL_ACTIVATION_OFFSET_LOW_THRESHOLD)
  757. finger_move_speed = 0;
  758. else
  759. {
  760. // Event timesing is not good for short period due to the events are queued without timestamp
  761. finger_move_speed = (float)diff_y * ((float)seconds_to_ticks(1) / (float)diff_ticks);
  762. if (abs(finger_move_speed) > SMOOTH_SCROLL_ACTIVATION_SPPED_THRESHOLD)
  763. {
  764. if (finger_move_speed > 0)
  765. {
  766. if (display_mode == DISPLAY_MODE_ARTICLE)
  767. finger_move_speed = ARTICLE_SMOOTH_SCROLL_SPEED_FACTOR *
  768. (finger_move_speed - SMOOTH_SCROLL_ACTIVATION_SPPED_THRESHOLD);
  769. else
  770. finger_move_speed = LIST_SMOOTH_SCROLL_SPEED_FACTOR *
  771. (finger_move_speed - SMOOTH_SCROLL_ACTIVATION_SPPED_THRESHOLD);
  772. }
  773. else
  774. {
  775. if (display_mode == DISPLAY_MODE_ARTICLE)
  776. finger_move_speed = ARTICLE_SMOOTH_SCROLL_SPEED_FACTOR *
  777. (finger_move_speed + SMOOTH_SCROLL_ACTIVATION_SPPED_THRESHOLD);
  778. else
  779. finger_move_speed = LIST_SMOOTH_SCROLL_SPEED_FACTOR *
  780. (finger_move_speed + SMOOTH_SCROLL_ACTIVATION_SPPED_THRESHOLD);
  781. }
  782. }
  783. else
  784. finger_move_speed = 0;
  785. }
  786. article_moved = false;
  787. if (finger_move_speed == 0 && b_show_scroll_bar)
  788. {
  789. b_show_scroll_bar = 0;
  790. show_scroll_bar(0); // clear scroll bar
  791. }
  792. article_scroll_pixel = INITIAL_ARTICLE_SCROLL_THRESHOLD;
  793. article_moved_pixels = 0;
  794. touch_y_last_unreleased = 0;
  795. start_move_time = 0;
  796. article_link_number = get_activated_article_link_number();
  797. if(article_link_number>=0)
  798. {
  799. if (link_to_be_inverted >= 0)
  800. {
  801. if (link_currently_inverted >= 0)
  802. invert_link(link_currently_inverted);
  803. invert_link(link_to_be_inverted);
  804. }
  805. if (finger_move_speed == 0)
  806. {
  807. init_invert_link();
  808. last_display_mode = display_mode;
  809. if (display_mode == DISPLAY_MODE_WIKI_SELECTION)
  810. {
  811. set_wiki(article_link_number);
  812. search_init();
  813. search_set_selection(-1);
  814. display_mode = DISPLAY_MODE_INDEX;
  815. keyboard_set_mode(KEYBOARD_CHAR);
  816. repaint_search();
  817. }
  818. else
  819. {
  820. if (display_mode == DISPLAY_MODE_ARTICLE)
  821. {
  822. saved_prev_idx_article = saved_idx_article;
  823. if (!(saved_prev_idx_article & 0xFF000000)) // idx_article for current wiki
  824. {
  825. saved_prev_idx_article |= get_wiki_id_from_idx(nCurrentWiki) << 24;
  826. }
  827. }
  828. else
  829. saved_prev_idx_article = 0;
  830. display_mode = DISPLAY_MODE_ARTICLE;
  831. open_article_link_with_link_number(article_link_number);
  832. }
  833. }
  834. else
  835. {
  836. if (link_currently_inverted >= 0)
  837. invert_link(link_currently_inverted);
  838. init_invert_link();
  839. }
  840. return;
  841. }
  842. reset_article_link_number();
  843. article_touch_down_handled = 0;
  844. } else {
  845. finger_touched = 1;
  846. finger_move_speed = 0;
  847. if(touch_y_last_unreleased == 0)
  848. {
  849. touch_y_last_unreleased = ev->touch_event.y;
  850. touch_y_last = ev->touch_event.y;
  851. last_unreleased_time = ev->touch_event.ticks;
  852. reset_article_link_number();
  853. article_moved_pixels = 0;
  854. last_5_x[0] = ev->touch_event.x;
  855. last_5_y[0] = ev->touch_event.y;
  856. last_5_y_time_ticks[0] = ev->touch_event.ticks;
  857. for (i = 1; i < 5; i++)
  858. {
  859. last_5_x[i] = -1;
  860. last_5_y[i] = -1;
  861. }
  862. }
  863. else
  864. {
  865. article_moved_pixels += touch_y_last - ev->touch_event.y;
  866. if(article_moved || abs(article_moved_pixels) > article_scroll_pixel)
  867. {
  868. if (!article_moved)
  869. {
  870. article_moved = true;
  871. reset_article_link_number();
  872. if (article_moved_pixels > 0)
  873. article_moved_pixels -= article_scroll_pixel;
  874. else
  875. article_moved_pixels += article_scroll_pixel;
  876. display_article_with_pcf(article_moved_pixels);
  877. article_scroll_pixel = ARTICLE_MOVING_SCROLL_THRESHOLD;
  878. }
  879. else if (finger_move_speed == 0)
  880. {
  881. display_article_with_pcf(touch_y_last - ev->touch_event.y);
  882. }
  883. for (i = 4; i >= 1; i--)
  884. {
  885. last_5_x[i] = last_5_x[i-1];
  886. last_5_y[i] = last_5_y[i-1];
  887. last_5_y_time_ticks[i] = last_5_y_time_ticks[i-1];
  888. }
  889. last_5_x[0] = ev->touch_event.x;
  890. last_5_y[0] = ev->touch_event.y;
  891. last_5_y_time_ticks[0] = ev->touch_event.ticks;
  892. b_show_scroll_bar = 1;
  893. }
  894. touch_y_last = ev->touch_event.y;
  895. }
  896. if (!article_moved && get_activated_article_link_number() < 0)
  897. {
  898. average_xy(&average_x, &average_y, last_5_x, last_5_y, last_5_y_time_ticks);
  899. article_link_number = isArticleLinkSelected(average_x, average_y);
  900. if (article_link_number >= 0)
  901. set_article_link_number(article_link_number, ev->touch_event.ticks);
  902. }
  903. if (!article_touch_down_handled) {
  904. article_touch_down_pos.x = ev->touch_event.x;
  905. article_touch_down_pos.y = ev->touch_event.y;
  906. article_touch_down_handled = 1;
  907. }
  908. }
  909. }
  910. out:
  911. return;
  912. }
  913. int wikilib_init (void)
  914. {
  915. init_lcd_draw_buf();
  916. init_file_buffer();
  917. init_wiki_info();
  918. return 0;
  919. }
  920. #ifndef INCLUDED_FROM_KERNEL
  921. extern long idx_init_article;
  922. #endif
  923. int wikilib_run(void)
  924. {
  925. int sleep;
  926. long time_now;
  927. struct wl_input_event ev;
  928. int more_events = 0;
  929. unsigned long last_event_time = 0;
  930. int rc;
  931. char *pMsg;
  932. /*
  933. * test searching code...
  934. */
  935. article_buf_pointer = NULL;
  936. search_init();
  937. history_list_init();
  938. malloc_status_simple();
  939. print_intro();
  940. #ifndef INCLUDED_FROM_KERNEL
  941. if (!load_init_article(idx_init_article))
  942. {
  943. display_mode = DISPLAY_MODE_ARTICLE;
  944. last_display_mode = DISPLAY_MODE_INDEX;
  945. }
  946. #endif
  947. pMsg = get_nls_text("type_a_word");
  948. render_string(SUBTITLE_FONT_IDX, -1, 55, pMsg, strlen(pMsg), 0);
  949. for (;;) {
  950. if (more_events)
  951. sleep = 0;
  952. else
  953. sleep = 1;
  954. if (!more_events && display_mode == DISPLAY_MODE_ARTICLE && render_article_with_pcf())
  955. sleep = 0;
  956. else if (!more_events && display_mode == DISPLAY_MODE_INDEX && render_search_result_with_pcf())
  957. sleep = 0;
  958. else if (!more_events && display_mode == DISPLAY_MODE_HISTORY && render_history_with_pcf())
  959. sleep = 0;
  960. else if (!more_events && display_mode == DISPLAY_MODE_WIKI_SELECTION && render_wiki_selection_with_pcf())
  961. sleep = 0;
  962. #ifdef OVER_SCROLL_ENABLED
  963. if ((finger_move_speed || over_scroll_lines) && !finger_touched)
  964. #else
  965. if (finger_move_speed && !finger_touched)
  966. #endif
  967. {
  968. scroll_article();
  969. sleep = 0;
  970. }
  971. #ifdef INCLUDED_FROM_KERNEL
  972. time_now = get_time_ticks();
  973. if(display_mode == DISPLAY_MODE_INDEX)
  974. {
  975. if (press_delete_button && get_search_string_len()>0)
  976. {
  977. sleep = 0;
  978. if(time_diff(time_now, start_search_time) > seconds_to_ticks(3.5))
  979. {
  980. if (!clear_search_string())
  981. {
  982. search_string_changed_remove = true;
  983. search_to_be_reloaded(SEARCH_TO_BE_RELOADED_SET, SEARCH_RELOAD_NO_POPULATE);
  984. }
  985. press_delete_button = false;
  986. }
  987. else if (time_diff(time_now, start_search_time) > seconds_to_ticks(0.5) &&
  988. time_diff(time_now, last_delete_time) > seconds_to_ticks(0.3))
  989. {
  990. if (!search_remove_char(0, time_now))
  991. {
  992. search_string_changed_remove = true;
  993. search_to_be_reloaded(SEARCH_TO_BE_RELOADED_SET, SEARCH_RELOAD_NO_POPULATE);
  994. }
  995. last_delete_time = time_now;
  996. }
  997. }
  998. }
  999. else if (display_mode == DISPLAY_MODE_RESTRICTED)
  1000. {
  1001. if (press_delete_button && get_password_string_len()>0)
  1002. {
  1003. sleep = 0;
  1004. time_now = get_time_ticks();
  1005. if(time_diff(time_now, start_search_time) > seconds_to_ticks(3.5))
  1006. {
  1007. clear_password_string();
  1008. press_delete_button = false;
  1009. }
  1010. else if (time_diff(time_now, start_search_time) > seconds_to_ticks(0.5) &&
  1011. time_diff(time_now, last_delete_time) > seconds_to_ticks(0.3))
  1012. {
  1013. password_remove_char();
  1014. last_delete_time = time_now;
  1015. }
  1016. }
  1017. }
  1018. #endif
  1019. if (!more_events && display_mode == DISPLAY_MODE_INDEX && fetch_search_result(0, 0, 0))
  1020. {
  1021. sleep = 0;
  1022. }
  1023. if (!more_events && display_mode == DISPLAY_MODE_INDEX && check_search_string_change())
  1024. {
  1025. sleep = 0;
  1026. }
  1027. if (keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_CHECK, 0)) // check if need to reset invert
  1028. sleep = 0;
  1029. if (check_invert_link()) // check if need to invert link
  1030. sleep = 0;
  1031. if (sleep)
  1032. {
  1033. if (time_diff(get_time_ticks(), last_event_time) > seconds_to_ticks(15))
  1034. rc = history_list_save(HISTORY_SAVE_POWER_OFF);
  1035. else
  1036. rc = history_list_save(HISTORY_SAVE_NORMAL);
  1037. if (rc > 0)
  1038. {
  1039. #ifdef INCLUDED_FROM_KERNEL
  1040. delay_us(200000); // for some reason, save may not work if no delay
  1041. #endif
  1042. }
  1043. else if (rc < 0)
  1044. sleep = 0; // waiting for last_event_time timeout to save the history
  1045. }
  1046. wl_input_wait(&ev, sleep);
  1047. more_events = 1;
  1048. switch (ev.type) {
  1049. case WL_INPUT_EV_TYPE_CURSOR:
  1050. handle_cursor(&ev);
  1051. last_event_time = get_time_ticks();
  1052. break;
  1053. case WL_INPUT_EV_TYPE_KEYBOARD:
  1054. if (ev.key_event.value != 0)
  1055. {
  1056. b_show_scroll_bar = 0;
  1057. handle_key_release(ev.key_event.keycode);
  1058. }
  1059. last_event_time = get_time_ticks();
  1060. break;
  1061. case WL_INPUT_EV_TYPE_TOUCH:
  1062. handle_touch(&ev);
  1063. last_event_time = ev.touch_event.ticks;
  1064. break;
  1065. default:
  1066. more_events = 0;
  1067. break;
  1068. }
  1069. }
  1070. /* never reached */
  1071. return 0;
  1072. }
  1073. unsigned long get_time_ticks(void)
  1074. {
  1075. long clock_ticks;
  1076. #ifdef INCLUDED_FROM_KERNEL
  1077. clock_ticks = Tick_get();
  1078. #else
  1079. clock_ticks = clock();
  1080. #endif
  1081. if (clock_ticks == 0)
  1082. clock_ticks = 1; // 0 is used for special purpose
  1083. return clock_ticks;
  1084. }
  1085. unsigned long time_diff(unsigned long t2, unsigned long t1)
  1086. {
  1087. unsigned long diff;
  1088. if (t2 < t1)
  1089. diff = (unsigned long) 0xFFFFFFFF - t1 + t2;
  1090. else
  1091. diff = t2 - t1;
  1092. return diff;
  1093. }
  1094. unsigned long seconds_to_ticks(float sec)
  1095. {
  1096. long clock_ticks;
  1097. #ifdef INCLUDED_FROM_KERNEL
  1098. clock_ticks = sec * 24000000;
  1099. #else
  1100. clock_ticks = sec * CLOCKS_PER_SEC;
  1101. #endif
  1102. return clock_ticks;
  1103. }
  1104. void fatal_error(char *sError)
  1105. {
  1106. struct wl_input_event ev;
  1107. guilib_fb_lock();
  1108. guilib_clear();
  1109. #ifndef INCLUDED_FROM_KERNEL
  1110. printf("Fatal error - %s\n", sError);
  1111. exit(-1);
  1112. #else
  1113. render_string(SUBTITLE_FONT_IDX, -1, 94, sError, strlen(sError), 0);
  1114. guilib_fb_unlock();
  1115. for (;;)
  1116. wl_input_wait(&ev, 1);
  1117. #endif
  1118. }