wiki_info.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*
  2. * Copyright (c) 2009 Openmoko Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <errno.h>
  23. #include <malloc-simple.h>
  24. #include <file-io.h>
  25. #include "wikilib.h"
  26. #include "lcd_buf_draw.h"
  27. #include "wiki_info.h"
  28. WIKI_LIST wiki_list[MAX_WIKIS] =
  29. {
  30. {1, "enpedia"},
  31. {2, "espedia"},
  32. {3, "frpedia"},
  33. {4, "depedia"},
  34. {5, "nlpedia"},
  35. {6, "ptpedia"},
  36. {7, "fipedia"},
  37. {8, "japedia"},
  38. };
  39. int nWikiCount = 0;
  40. int aWikiInfoIdx[MAX_WIKIS_PER_DEVICE]; // index to wiki_info[]
  41. char *aWikiNls[MAX_WIKIS_PER_DEVICE];
  42. long aWikiNlsLen[MAX_WIKIS_PER_DEVICE];
  43. int nCurrentWiki = -1; // index to aWikiInfoIdx[]
  44. int rendered_wiki_selection_count = -1;
  45. int current_article_wiki_id = 0;
  46. WIKI_LICENSE_DRAW aWikiLicenseDraw[MAX_WIKIS_PER_DEVICE];
  47. void init_wiki_info(void)
  48. {
  49. int i;
  50. int fd;
  51. char sFilePath[20];
  52. unsigned int nSize;
  53. char *p;
  54. int nWikiId;
  55. for (i = 0; i < MAX_WIKIS && nWikiCount < MAX_WIKIS_PER_DEVICE; i++)
  56. {
  57. sprintf(sFilePath, "%s/wiki.idx", wiki_list[i].wiki_folder);
  58. fd = wl_open(sFilePath, WL_O_RDONLY);
  59. if (fd >= 0)
  60. {
  61. aWikiInfoIdx[nWikiCount] = i;
  62. nWikiCount++;
  63. wl_close(fd);
  64. }
  65. }
  66. if (nWikiCount > 0)
  67. {
  68. nCurrentWiki = 0;
  69. fd = wl_open("wiki.ini", WL_O_RDONLY);
  70. wl_fsize(fd, &nSize);
  71. p = malloc_simple(nSize + 1, MEM_TAG_INDEX_M1);
  72. if (p)
  73. {
  74. wl_read(fd, p, nSize);
  75. wl_close(fd);
  76. p[nSize] = '\0';
  77. nWikiId = atoi(p);
  78. if (nWikiId > 0)
  79. nCurrentWiki = get_wiki_idx_from_id(nWikiId);
  80. if (nCurrentWiki < 0)
  81. nCurrentWiki = 0;
  82. free_simple(p, MEM_TAG_INDEX_M1);
  83. }
  84. for (i = 0; i < nWikiCount; i++)
  85. {
  86. aWikiNlsLen[i] = -1;
  87. aWikiLicenseDraw[i].lines = 0;
  88. }
  89. }
  90. else
  91. fatal_error("No wiki found");
  92. }
  93. char *get_wiki_file_path(int nWikiIdx, char *file_name)
  94. {
  95. static char sFilePath[32];
  96. sprintf(sFilePath, "%s/%s", wiki_list[aWikiInfoIdx[nWikiIdx]].wiki_folder, file_name);
  97. return sFilePath;
  98. }
  99. int get_wiki_count(void)
  100. {
  101. return nWikiCount;
  102. }
  103. int get_wiki_idx_from_id(int wiki_id)
  104. {
  105. int i;
  106. if (wiki_id <= 0)
  107. return nCurrentWiki;
  108. for (i = 0; i < nWikiCount; i++)
  109. {
  110. if (wiki_list[aWikiInfoIdx[i]].wiki_id == wiki_id)
  111. return i;
  112. }
  113. return -1;
  114. }
  115. int get_wiki_id_from_idx(int wiki_idx)
  116. {
  117. if (wiki_idx < nWikiCount)
  118. {
  119. return wiki_list[aWikiInfoIdx[wiki_idx]].wiki_id;
  120. }
  121. return 0;
  122. }
  123. unsigned char *get_nls_key_value(char *key, char *key_pairs, long key_pairs_len)
  124. {
  125. int i, j;
  126. int key_len = strlen(key);
  127. int bFound = 0;
  128. i = 0;
  129. while (i < key_pairs_len - key_len - 1 && !bFound)
  130. {
  131. for (j = 0; j < key_len; j++)
  132. {
  133. if (key[j] != key_pairs[i + j])
  134. break;
  135. }
  136. i += j;
  137. if (j == key_len && key_pairs[i] == '=')
  138. {
  139. bFound = 1;
  140. }
  141. else
  142. {
  143. while (key_pairs[i] != '\0')
  144. i++;
  145. while (i < key_pairs_len - key_len - 1 && key_pairs[i] == '\0')
  146. i++;
  147. }
  148. }
  149. if (bFound)
  150. return &key_pairs[i + 1];
  151. else
  152. return "";
  153. }
  154. unsigned char *get_nls_text(char *key)
  155. {
  156. int fd;
  157. unsigned int nSize;
  158. char *p;
  159. if (nCurrentWiki < 0)
  160. return "";
  161. else
  162. {
  163. if (aWikiNlsLen[nCurrentWiki] < 0)
  164. {
  165. fd = wl_open(get_wiki_file_path(nCurrentWiki, "wiki.nls"), WL_O_RDONLY);
  166. if (fd >= 0)
  167. {
  168. wl_fsize(fd, &nSize);
  169. aWikiNlsLen[nCurrentWiki] = nSize;
  170. aWikiNls[nCurrentWiki] = malloc_simple(nSize + 1, MEM_TAG_INDEX_M1);
  171. if (aWikiNls[nCurrentWiki])
  172. {
  173. wl_read(fd, aWikiNls[nCurrentWiki], nSize);
  174. wl_close(fd);
  175. aWikiNls[nCurrentWiki][nSize] = '\0';
  176. p = aWikiNls[nCurrentWiki];
  177. while (*p)
  178. {
  179. if (*p == '\r' || *p == '\n')
  180. *p = '\0';
  181. p++;
  182. }
  183. }
  184. else
  185. aWikiNlsLen[nCurrentWiki] = 0;
  186. }
  187. else
  188. {
  189. aWikiNlsLen[nCurrentWiki] = 0;
  190. }
  191. }
  192. if (aWikiNlsLen[nCurrentWiki] == 0)
  193. return "";
  194. return get_nls_key_value(key, aWikiNls[nCurrentWiki], aWikiNlsLen[nCurrentWiki]);
  195. }
  196. }
  197. void wiki_selection(void)
  198. {
  199. rendered_wiki_selection_count = 0;
  200. render_wiki_selection_with_pcf();
  201. }
  202. char *get_wiki_name(int idx)
  203. {
  204. int nTmpeCurrentWiki = nCurrentWiki;
  205. char *pName;
  206. nCurrentWiki = idx;
  207. pName = get_nls_text("wiki_name");
  208. nCurrentWiki = nTmpeCurrentWiki;
  209. return pName;
  210. }
  211. void set_wiki(int idx)
  212. {
  213. int fd;
  214. char sWikiId[10];
  215. nCurrentWiki = idx;
  216. fd = wl_open("wiki.ini", WL_O_CREATE);
  217. if (fd >= 0)
  218. {
  219. sprintf(sWikiId, "%d", get_wiki_id_from_idx(nCurrentWiki));
  220. wl_write(fd, (void *)sWikiId, strlen(sWikiId));
  221. wl_close(fd);
  222. }
  223. }
  224. void nls_replace_text(char *replace_str, char *out_str)
  225. {
  226. if (!strcmp(replace_str, "title"))
  227. {
  228. extract_title_from_article(out_str);
  229. while (*out_str)
  230. {
  231. if (*out_str == ' ')
  232. *out_str = '_';
  233. out_str++;
  234. }
  235. }
  236. else
  237. {
  238. strcpy(out_str, replace_str);
  239. }
  240. }
  241. WIKI_LICENSE_DRAW *wiki_license_draw()
  242. {
  243. int wiki_idx = get_wiki_idx_from_id(current_article_wiki_id);
  244. if (wiki_idx < 0)
  245. wiki_idx = nCurrentWiki;
  246. // if (!aWikiLicenseDraw[wiki_idx].lines)
  247. {
  248. int y = 0;
  249. int x = 0;
  250. char draw_buf[MAX_LICENSE_TEXT_PIXEL_LINES * LCD_BUF_WIDTH_BYTES];
  251. unsigned char *pLicenseText = get_nls_text("license_text");
  252. char sLicenseTextSegment[MAX_LICENSE_TEXT_LEN];
  253. unsigned char *pLicenseTextSegment;
  254. int line_height = pcfFonts[LICENSE_TEXT_FONT - 1].Fmetrics.linespace;
  255. char str[256];
  256. unsigned char *p, *q;
  257. int bInLink = 0;
  258. int nLinkArticleId = 0;
  259. int width;
  260. int start_x, start_y, end_x, end_y;
  261. int i;
  262. aWikiLicenseDraw[wiki_idx].link_count = 0;
  263. memset(draw_buf, 0, sizeof(draw_buf));
  264. sLicenseTextSegment[0] = '\0';
  265. pLicenseTextSegment = sLicenseTextSegment;
  266. while (*pLicenseText && y < MAX_LICENSE_TEXT_PIXEL_LINES)
  267. {
  268. if (!*pLicenseTextSegment)
  269. {
  270. if (pLicenseText[0] == LICENSE_LINK_START)
  271. {
  272. bInLink = 1;
  273. nLinkArticleId++;
  274. pLicenseText++;
  275. if ((p = strchr(pLicenseText, LICENSE_LINK_END)))
  276. {
  277. memcpy(sLicenseTextSegment, pLicenseText, p - pLicenseText);
  278. sLicenseTextSegment[p - pLicenseText] = '\0';
  279. pLicenseText = p + 1;
  280. }
  281. else
  282. {
  283. strcpy(sLicenseTextSegment, pLicenseText);
  284. pLicenseText += strlen(pLicenseText);
  285. }
  286. }
  287. else if (pLicenseText[0] == NLS_TEXT_REPLACEMENT_START)
  288. {
  289. bInLink = 0;
  290. pLicenseText++;
  291. if ((p = strchr(pLicenseText, NLS_TEXT_REPLACEMENT_END)))
  292. {
  293. memcpy(str, pLicenseText, p - pLicenseText);
  294. str[p - pLicenseText] = '\0';
  295. pLicenseText = p + 1;
  296. }
  297. else
  298. {
  299. strcpy(str, pLicenseText);
  300. pLicenseText += strlen(pLicenseText);
  301. }
  302. nls_replace_text(str, sLicenseTextSegment);
  303. }
  304. else
  305. {
  306. bInLink = 0;
  307. p = strchr(pLicenseText, LICENSE_LINK_START);
  308. q = strchr(pLicenseText, NLS_TEXT_REPLACEMENT_START);
  309. if ((p && q && p > q) || (!p))
  310. p = q;
  311. if (p)
  312. {
  313. memcpy(sLicenseTextSegment, pLicenseText, p - pLicenseText);
  314. sLicenseTextSegment[p - pLicenseText] = '\0';
  315. pLicenseText = p;
  316. }
  317. else
  318. {
  319. strcpy(sLicenseTextSegment, pLicenseText);
  320. pLicenseText += strlen(pLicenseText);
  321. }
  322. }
  323. pLicenseTextSegment = sLicenseTextSegment;
  324. }
  325. while (*pLicenseTextSegment && y < MAX_LICENSE_TEXT_PIXEL_LINES)
  326. {
  327. if (!x)
  328. {
  329. while (*pLicenseTextSegment == ' ')
  330. pLicenseTextSegment++;
  331. }
  332. width = extract_str_fitting_width(&pLicenseTextSegment, str, LCD_BUF_WIDTH_PIXELS - x - LCD_LEFT_MARGIN, LICENSE_TEXT_FONT);
  333. p = str;
  334. buf_draw_UTF8_str_in_copy_buffer(draw_buf, &p, x, LCD_BUF_WIDTH_PIXELS,
  335. y, y + line_height - 1, LCD_LEFT_MARGIN, LICENSE_TEXT_FONT);
  336. if (bInLink && aWikiLicenseDraw[wiki_idx].link_count < MAX_LINKS_IN_LICENSE_TEXT)
  337. {
  338. start_x = x;
  339. start_y = y + 1;
  340. end_x = x + width;
  341. end_y = y + line_height;
  342. aWikiLicenseDraw[wiki_idx].links[aWikiLicenseDraw[wiki_idx].link_count].start_xy = (unsigned long)(start_x | (start_y << 8));
  343. aWikiLicenseDraw[wiki_idx].links[aWikiLicenseDraw[wiki_idx].link_count].end_xy = (unsigned long)(end_x | (end_y << 8));
  344. aWikiLicenseDraw[wiki_idx].links[aWikiLicenseDraw[wiki_idx].link_count++].article_id = nLinkArticleId;
  345. for(i = start_x + LCD_LEFT_MARGIN; i < end_x + LCD_LEFT_MARGIN; i++)
  346. {
  347. lcd_set_pixel(draw_buf, i, end_y + 1);
  348. }
  349. }
  350. if (*pLicenseTextSegment)
  351. {
  352. x = 0;
  353. y += line_height;
  354. }
  355. else
  356. x += width;
  357. }
  358. }
  359. if (x)
  360. y += line_height;
  361. y += SPACE_AFTER_LICENSE_TEXT;
  362. aWikiLicenseDraw[wiki_idx].lines = y;
  363. aWikiLicenseDraw[wiki_idx].buf = malloc_simple(y * LCD_BUF_WIDTH_BYTES, MEM_TAG_INDEX_M1);
  364. memcpy(aWikiLicenseDraw[wiki_idx].buf, draw_buf, y * LCD_BUF_WIDTH_BYTES);
  365. }
  366. return &aWikiLicenseDraw[wiki_idx];
  367. }