Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1000 lines (911 sloc) 25.429 kb
/*
* Copyright (c) 2009 Openmoko Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <grifo.h>
#include "ustring.h"
#include "wikilib.h"
#include "lcd_buf_draw.h"
#include "wiki_info.h"
#include "search.h"
#include "search_fnd.h"
#include "guilib.h"
WIKI_LIST wiki_list_default[] = {
{1, 1, WIKI_CAT_ENCYCLOPAEDIA, "en", "enpedia", KEYBOARD_CHAR, ""},
};
WIKI_LIST *wiki_list;
unsigned int nWikiList = 0;
bool *baWikiActive;
extern int search_interrupted;
unsigned int nWikiCount = 0;
int nCurrentWiki = -1; // index to aActiveWikis[].WikiInfoIdx
bool bWikiIsDanish = false;
bool bWikiIsJapanese = false;
bool bWikiIsKorean = false;
bool bWikiIsTC = false;
KEYBOARD_MODE default_keyboard = KEYBOARD_CHAR;
int rendered_wiki_selection_count = -1;
int current_article_wiki_id = 0;
// store the wiki.ini file contents
#define WIKI_INI_NAME "wiki.ini"
unsigned char *pWikiIni = NULL;
#define MIN_WIKI_INI_ALLOCATION 32
unsigned long sizeWikiIni = 0; // the number of bytes allocated to pWikiIni
unsigned long lenWikiIni = 0; // the number of bytes in use in pWikiIni
PACTIVE_WIKI aActiveWikis = NULL;
extern int bShowPositioner;
WIKI_LICENSE_DRAW *pWikiLicenseDraw;
const unsigned char *get_nls_key_value(const char *key, unsigned char *key_pairs, long key_pairs_len);
int get_wiki_idx_from_serial_id(int wiki_serial_id);
#define MAX_LINE_SIZE 256
static ssize_t copy_line(char *buf, char *line, ssize_t nLineChars)
{
ssize_t len_left;
int i = 0;
while (i < nLineChars && i < MAX_LINE_SIZE - 1 && line[i] != '\r' && line[i] != '\n')
i++;
if (i > 0)
memcpy(buf, line, i);
buf[i] = '\0';
while (i < nLineChars && (line[i] == '\r' || line[i] == '\n'))
i++;
len_left = nLineChars - i;
if (len_left > 0)
memmove(line, &line[i], len_left);
return len_left;
}
static void trim_leading_spaces(char *buf)
{
int i = 0;
while (buf[i] && strchr(" \t\r\n", buf[i]))
i++;
if (i > 0)
{
int nMoveLen = strlen(buf) - i;
memmove(buf, &buf[i], nMoveLen + 1);
}
}
static void trim_trailing_spaces(char *buf)
{
int i = strlen(buf);
while (i && strchr(" \t\r\n", buf[i]))
i--;
buf[i + 1] = '\0';
}
static WIKI_CAT_E get_category_info(char *word)
{
if (!word[0] || !strcmp(word, "ENCYCLOPAEDIA"))
return WIKI_CAT_ENCYCLOPAEDIA;
else if (!strcmp(word, "TRAVEL"))
return WIKI_CAT_TRAVEL;
else if (!strcmp(word, "DICTIONARY"))
return WIKI_CAT_DICTIONARY;
else if (!strcmp(word, "QUOTE"))
return WIKI_CAT_QUOTE;
else if (!strcmp(word, "SOURCE"))
return WIKI_CAT_SOURCE;
else if (!strcmp(word, "BOOKS"))
return WIKI_CAT_BOOKS;
else if (!strcmp(word, "GUTENBERG"))
return WIKI_CAT_GUTENBERG;
else if (!strcmp(word, "OTHERS"))
return WIKI_CAT_OTHERS;
else
return WIKI_CAT_INVALID;
}
static KEYBOARD_MODE get_keyboard_info(char *word)
{
if (!word[0] || !strcmp(word, "ENGLISH") || !strcmp(word, "CHINESE-PINYIN"))
return KEYBOARD_CHAR;
else if (!strcmp(word, "JAPANESE-HIRAGANA"))
return KEYBOARD_PHONE_STYLE_JP;
else if (!strcmp(word, "JAPANESE-ROMAN"))
return KEYBOARD_CHAR_JP;
else if (!strcmp(word, "KOREAN"))
return KEYBOARD_CHAR_KO;
else if (!strcmp(word, "DANISH"))
return KEYBOARD_CHAR_DA;
else if (!strcmp(word, "CHINESE-BOPOMO"))
return KEYBOARD_PHONE_STYLE_TW;
else
return KEYBOARD_NONE;
}
static int assign_wiki_id(char *word)
{
unsigned int i;
int max_wiki_id = 0;
for (i = 0; i < nWikiList; i++)
{
if (!strcmp(word, wiki_list[i].wiki_folder))
return wiki_list[i].wiki_id;
if (max_wiki_id < wiki_list[i].wiki_id)
max_wiki_id = wiki_list[i].wiki_id;
}
return max_wiki_id + 1;
}
static void str_to_upper(char *word)
{
unsigned int i;
for (i = 0; i < strlen(word); i++)
word[i] = toupper(word[i]);
}
static void str_to_lower(char *word)
{
unsigned int i;
for (i = 0; i < strlen(word); i++)
word[i] = tolower(word[i]);
}
static bool get_next_token(char *word, char *buf)
{
static char *last = NULL;
if (buf)
last = buf;
if (word && last && *last)
{
while (last && *last && *last != ',')
*word++ = *last++;
if (*last == ',')
last++;
*word = '\0';
return true;
}
return false;
}
void init_wiki_info(void)
{
unsigned int i, j;
int fd;
int nWikiSerialId;
char line[MAX_LINE_SIZE], buf[MAX_LINE_SIZE], word[MAX_LINE_SIZE];
ssize_t nLineChars;
nWikiCount = 0;
fd = file_open("wiki.inf", FILE_OPEN_READ);
if (fd >= 0)
{
unsigned int nTempWikiList = 0;
nLineChars = file_read(fd, line, MAX_LINE_SIZE);
while (nLineChars > 0)
{
nLineChars = copy_line(buf, line, nLineChars);
trim_leading_spaces(buf);
if (buf[0] && buf[0] != '#')
nTempWikiList++;
nLineChars += file_read(fd, &line[nLineChars], MAX_LINE_SIZE - nLineChars);
}
if (nTempWikiList > 0)
{
if (nTempWikiList > sizeof(wiki_list) / sizeof(WIKI_LIST))
wiki_list = (WIKI_LIST *)memory_allocate(sizeof(WIKI_LIST) * nTempWikiList, "wiki_list");
else
wiki_list = wiki_list_default;
file_lseek(fd, 0);
nLineChars = file_read(fd, line, MAX_LINE_SIZE);
while (nLineChars > 0)
{
nLineChars = copy_line(buf, line, nLineChars);
trim_leading_spaces(buf);
if (buf[0] && buf[0] != '#')
{
int state = 0;
memset(&wiki_list[nWikiList], 0, sizeof(WIKI_LIST));
wiki_list[nWikiList].wiki_default_keyboard = KEYBOARD_CHAR; // default keyboard
get_next_token(NULL, buf); // initialize get_next_token()
while (get_next_token(word, NULL))
{
trim_leading_spaces(word);
trim_trailing_spaces(word);
switch (state)
{
case 0:
str_to_upper(word);
wiki_list[nWikiList].wiki_cat = get_category_info(word);
if (wiki_list[nWikiList].wiki_cat != WIKI_CAT_INVALID)
state++;
else
state = 99;
break;
case 1:
strncpy(wiki_list[nWikiList].wiki_lang, word, sizeof(wiki_list[nWikiList].wiki_lang) - 1);
wiki_list[nWikiList].wiki_lang[sizeof(wiki_list[nWikiList].wiki_lang) - 1] = '\0';
if (wiki_list[nWikiList].wiki_lang[0])
state++;
else
state = 99;
break;
case 2:
str_to_lower(word);
strncpy(wiki_list[nWikiList].wiki_folder, word, sizeof(wiki_list[nWikiList].wiki_folder) - 1);
wiki_list[nWikiList].wiki_folder[sizeof(wiki_list[nWikiList].wiki_folder) - 1] = '\0';
if (wiki_list[nWikiList].wiki_folder[0])
{
wiki_list[nWikiList].wiki_id = assign_wiki_id(word);
state++;
}
else
state = 99;
break;
case 3:
str_to_upper(word);
wiki_list[nWikiList].wiki_default_keyboard = get_keyboard_info(word);
if (wiki_list[nWikiList].wiki_default_keyboard != KEYBOARD_NONE)
state++;
else
state = 99;
break;
case 4:
// whole structure was cleared
// so copy n-1 bytes
strncpy((char *)wiki_list[nWikiList].wiki_menu_extra, word, sizeof(wiki_list[nWikiList].wiki_menu_extra) - 1);
state++;
break;
default:
break;
}
}
if (wiki_list[nWikiList].wiki_cat != WIKI_CAT_INVALID &&
wiki_list[nWikiList].wiki_lang[0] &&
wiki_list[nWikiList].wiki_folder[0] &&
wiki_list[nWikiList].wiki_default_keyboard != KEYBOARD_NONE)
{
wiki_list[nWikiList].wiki_serial_id = nWikiList + 1;
nWikiList++;
}
}
nLineChars += file_read(fd, &line[nLineChars], MAX_LINE_SIZE - nLineChars);
}
}
}
if (!nWikiList)
{
wiki_list = wiki_list_default;
nWikiList = sizeof(wiki_list_default) / sizeof(WIKI_LIST);
}
baWikiActive = (bool *)memory_allocate(sizeof(bool) * nWikiList, "baWikiActive");
memset(baWikiActive, 0, sizeof(bool) * nWikiList);
for (i = 0; i < nWikiList; i++)
{
if (directory_exists(wiki_list[i].wiki_folder))
{
baWikiActive[i] = true;
nWikiCount++;
}
}
if (nWikiCount > 0)
{
pWikiLicenseDraw = (PWIKI_LICENSE_DRAW)memory_allocate(sizeof(WIKI_LICENSE_DRAW), "wikiinfo0");
aActiveWikis = (PACTIVE_WIKI)memory_allocate(sizeof(ACTIVE_WIKI) * nWikiCount, "wikiinfo1");
if (!pWikiLicenseDraw || !aActiveWikis)
{
fatal_error("too many wikis");
}
pWikiLicenseDraw->lines = 0;
j = 0;
for (i = 0; i < nWikiList; i++)
{
if (baWikiActive[i])
aActiveWikis[j++].WikiInfoIdx = i;
}
nCurrentWiki = 0;
fd = file_open(WIKI_INI_NAME, FILE_OPEN_READ);
if (fd >= 0)
{
file_size(WIKI_INI_NAME, &lenWikiIni);
sizeWikiIni = lenWikiIni + MIN_WIKI_INI_ALLOCATION; // reserve space for wiki_id key pair
pWikiIni = memory_allocate(sizeWikiIni, "wikiinfo2");
if (pWikiIni)
{
memset(pWikiIni, 0, sizeWikiIni);
file_read(fd, pWikiIni, lenWikiIni);
file_close(fd);
pWikiIni[lenWikiIni] = '\0'; // safe because extra bytes were allocated
unsigned char *p0 = pWikiIni;
while (*p0)
{
if (*p0 == '\r' || *p0 == '\n')
*p0 = '\0';
p0++;
}
const unsigned char *p = get_nls_key_value("positioner", pWikiIni, lenWikiIni);
if (*p)
bShowPositioner = atoi((const char *)p);
p = get_nls_key_value("wiki_id", pWikiIni, lenWikiIni);
if (*p)
{
nWikiSerialId = atoi((const char *)p);
if (nWikiSerialId > 0)
nCurrentWiki = get_wiki_idx_from_serial_id(nWikiSerialId);
if (nCurrentWiki < 0)
nCurrentWiki = 0;
}
else
{
lenWikiIni = 0; // if no wiki_id entry in wiki.ini, reset the content of wiki.ini
nCurrentWiki = 0;
}
}
}
else
{
lenWikiIni = 0;
sizeWikiIni = MIN_WIKI_INI_ALLOCATION;
pWikiIni = memory_allocate(sizeWikiIni, "wikiinfo3");
if (pWikiIni)
{
memset(pWikiIni, 0, sizeWikiIni);
}
}
for (i = 0; i < nWikiCount; i++)
{
aActiveWikis[i].WikiNlsLen = -1;
}
if (!ustrcmp(wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_lang, "ja"))
bWikiIsJapanese = true;
else
bWikiIsJapanese = false;
if (!ustrcmp(wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_lang, "zht")) // Simplified Chinese Pinyin IME does not need special conversion
bWikiIsTC = true;
else
bWikiIsTC = false;
if (!ustrcmp(wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_lang, "ko"))
bWikiIsKorean = true;
else
bWikiIsKorean = false;
if (!ustrcmp(wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_lang, "da"))
bWikiIsDanish = true;
else
bWikiIsDanish = false;
default_keyboard = wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_default_keyboard;
keyboard_set_mode(default_keyboard);
} else {
fatal_error("No wiki found");
}
}
int get_wiki_idx_by_lang_link(const unsigned char *lang_link_str)
{
int len;
unsigned char *p, *q;
unsigned int i;
int current_wiki_cat = -1;
p = ustrchr(lang_link_str, ':');
q = ustrchr(lang_link_str, '#');
if (!p || (q && q < p))
p = q;
if (p)
{
int wiki_idx = get_wiki_idx_from_id(current_article_wiki_id);
current_wiki_cat = wiki_list[aActiveWikis[wiki_idx].WikiInfoIdx].wiki_cat;
len = p - lang_link_str;
for (i = 0; i < nWikiCount; i++)
{
if (current_wiki_cat == (int)wiki_list[aActiveWikis[i].WikiInfoIdx].wiki_cat &&
!ustrncmp(lang_link_str, wiki_list[aActiveWikis[i].WikiInfoIdx].wiki_lang, len))
return i;
}
}
return -1;
}
bool wiki_lang_exist(const unsigned char *lang_link_str)
{
return get_wiki_idx_by_lang_link(lang_link_str) >= 0;
}
bool wiki_keyboard_conversion_needed()
{
return bWikiIsJapanese || bWikiIsTC || bWikiIsKorean || bWikiIsDanish;
}
bool wiki_is_japanese()
{
return bWikiIsJapanese;
}
bool wiki_is_TC()
{
return bWikiIsTC;
}
bool wiki_is_korean()
{
return bWikiIsKorean;
}
bool wiki_is_danish()
{
return bWikiIsDanish;
}
KEYBOARD_MODE wiki_default_keyboard()
{
return default_keyboard;
}
uint32_t wiki_lang_link_search(const unsigned char *lang_link_str)
{
uint32_t article_idx = 0;
int nTempCurrentWiki = nCurrentWiki;
unsigned char *p, *q;
search_interrupted = 0;
if ((nCurrentWiki = get_wiki_idx_by_lang_link(lang_link_str)) >= 0)
{
reset_search_info(nCurrentWiki);
init_search_fnd();
p = ustrchr(lang_link_str, ':');
q = ustrchr(lang_link_str, '#');
if (!p || (q && q < p))
p = q;
if (p && q && q > p)
*q = '\0'; // truncate # in title, e.g., en:Tokyo#Cities
if (p)
{
if (*p == '#') // actual title is different than title for search
{
q = ustrchr(p + 1, CHAR_LANGUAGE_LINK_TITLE_DELIMITER); // locate the actual title
if (!q)
q = p;
}
else
q = p;
article_idx = get_article_idx_by_title(p + 1, q + 1);
if (article_idx)
article_idx |= wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_id << 24;
}
}
nCurrentWiki = nTempCurrentWiki;
return article_idx;
}
char *get_wiki_file_path(int nWikiIdx, char *file_name)
{
static char sFilePath[32];
sprintf(sFilePath, "%s/%s", wiki_list[aActiveWikis[nWikiIdx].WikiInfoIdx].wiki_folder, file_name);
return sFilePath;
}
int get_wiki_count(void)
{
return nWikiCount;
}
int get_wiki_idx_from_id(int wiki_id)
{
unsigned int i;
if (wiki_id <= 0)
return nCurrentWiki;
for (i = 0; i < nWikiCount; i++)
{
if (wiki_list[aActiveWikis[i].WikiInfoIdx].wiki_id == wiki_id)
return i;
}
return -1;
}
int get_wiki_idx_from_serial_id(int wiki_serial_id)
{
unsigned int i;
for (i = 0; i < nWikiCount; i++)
{
if (wiki_list[aActiveWikis[i].WikiInfoIdx].wiki_serial_id == wiki_serial_id)
return i;
}
return -1;
}
int get_wiki_id_from_idx(unsigned int wiki_idx)
{
if (wiki_idx < nWikiCount)
{
return wiki_list[aActiveWikis[wiki_idx].WikiInfoIdx].wiki_id;
}
return 0;
}
int get_wiki_serial_id_from_idx(unsigned int wiki_idx)
{
if (wiki_idx < nWikiCount)
{
return wiki_list[aActiveWikis[wiki_idx].WikiInfoIdx].wiki_serial_id;
}
return 0;
}
// key is a string e.g. "key1"
// key_pairs is a string like "key1=value1<NUL+>key2=value2<NUL*>"
// ^1 or more ^optional
// key_pairs_len is the number of bytes in key_pairs
// returns pointer to first byte of value string
const unsigned char *get_nls_key_value(const char *key, unsigned char *key_pairs, long key_pairs_len)
{
int i, j;
int key_len;
int bFound = 0;
key_len = ustrlen(key);
i = 0;
while (i < key_pairs_len - key_len - 1 && !bFound)
{
for (j = 0; j < key_len; j++)
{
if (key[j] != key_pairs[i + j])
break;
}
i += j;
if (j == key_len && key_pairs[i] == '=')
{
bFound = 1;
}
else
{
while (key_pairs[i] != '\0')
i++;
while (i < key_pairs_len - key_len - 1 && key_pairs[i] == '\0')
i++;
}
}
if (bFound)
return &key_pairs[i + 1];
else
return (const unsigned char *)"";
}
const unsigned char *get_nls_text(const char *key)
{
int fd;
unsigned long nSize;
unsigned char *p;
if (nCurrentWiki < 0)
return (const unsigned char *)"";
else
{
if (aActiveWikis[nCurrentWiki].WikiNlsLen < 0)
{
fd = file_open(get_wiki_file_path(nCurrentWiki, "wiki.nls"), FILE_OPEN_READ);
if (fd >= 0)
{
file_size(get_wiki_file_path(nCurrentWiki, "wiki.nls"), &nSize);
aActiveWikis[nCurrentWiki].WikiNlsLen = nSize;
aActiveWikis[nCurrentWiki].WikiNls = memory_allocate(nSize + 1, "wikiinfo4");
if (aActiveWikis[nCurrentWiki].WikiNls)
{
file_read(fd, aActiveWikis[nCurrentWiki].WikiNls, nSize);
file_close(fd);
aActiveWikis[nCurrentWiki].WikiNls[nSize] = '\0';
p = aActiveWikis[nCurrentWiki].WikiNls;
while (*p)
{
if (*p == '\r' || *p == '\n')
*p = '\0';
p++;
}
}
else
aActiveWikis[nCurrentWiki].WikiNlsLen = 0;
}
else
{
aActiveWikis[nCurrentWiki].WikiNlsLen = 0;
}
}
if (aActiveWikis[nCurrentWiki].WikiNlsLen == 0)
return (const unsigned char *)"";
return get_nls_key_value(key, aActiveWikis[nCurrentWiki].WikiNls, aActiveWikis[nCurrentWiki].WikiNlsLen);
}
}
const unsigned char *get_lang_link_display_text(const unsigned char *lang_link_str)
{
int nTempCurrentWiki = nCurrentWiki;
static unsigned char lang_str[3];
const unsigned char *p = NULL;
if ((nCurrentWiki = get_wiki_idx_by_lang_link(lang_link_str)) >= 0)
{
p = get_nls_text("lang_str");
if (p[0] == '\0')
p = NULL;
}
if (!p)
{
memcpy(lang_str, lang_link_str, 2);
lang_str[2] = '\0';
p = lang_str;
}
nCurrentWiki = nTempCurrentWiki;
return p;
}
void wiki_selection(void)
{
rendered_wiki_selection_count = 0;
render_wiki_selection_with_pcf();
}
const unsigned char *get_wiki_name(int idx)
{
int nTempCurrentWiki = nCurrentWiki;
const unsigned char *pName;
nCurrentWiki = idx;
pName = get_nls_text("wiki_name");
nCurrentWiki = nTempCurrentWiki;
return pName;
}
// I think this will only work if get_wiki_name has just been called
const unsigned char *get_wiki_extra_name(int idx)
{
return wiki_list[aActiveWikis[idx].WikiInfoIdx].wiki_menu_extra;
}
// pWikiIni = start of storage
// = "key1=values<NUL>key2=value2<NUL>"
// lenWikiIni = currently in-use byte count
// sizeWikiIni = total available byte count
void wiki_ini_insert_keypair(const char *key, const char *keyval)
{
const unsigned char *p_value = get_nls_key_value(key, pWikiIni, lenWikiIni);
unsigned long key_len = ustrlen(key);
unsigned long value_len = ustrlen(keyval);
unsigned char *afterEnd = pWikiIni + lenWikiIni;
// if the returned pointer is within the writable area cast away the const
if (p_value >= pWikiIni && p_value < afterEnd)
{
unsigned char *p_start = (unsigned char *)p_value - key_len - 1; // first byte of key
unsigned char *p = (unsigned char *)p_value;
while (p < afterEnd && '\0' != *p)
{
++p;
}
while (p < afterEnd && '\0' == *p)
{
++p;
}
long int move_size = lenWikiIni - (p_start - pWikiIni); // number of bytes after this key to end
memmove(p_start, p, move_size);
lenWikiIni -= p - p_start;
}
// strip trailing NULs
while (lenWikiIni > 0 && '\0' == pWikiIni[lenWikiIni - 1])
{
--lenWikiIni;
}
// if string is not empty append NUL
if (lenWikiIni > 0 && lenWikiIni < sizeWikiIni && lenWikiIni > 0)
{
pWikiIni[lenWikiIni++] = '\0';
}
// append key=new_value<NUL>
if (lenWikiIni + key_len + value_len + 2 <= sizeWikiIni)
{
memcpy(&pWikiIni[lenWikiIni], key, key_len);
lenWikiIni += key_len;
pWikiIni[lenWikiIni++] = '=';
memcpy(&pWikiIni[lenWikiIni], keyval, value_len);
lenWikiIni += value_len;
pWikiIni[lenWikiIni++] = '\0';
}
}
void set_wiki(int idx)
{
int fd;
nCurrentWiki = idx;
reset_search_info(nCurrentWiki);
if (!ustrcmp(wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_lang, "ja"))
bWikiIsJapanese = true;
else
bWikiIsJapanese = false;
if (!ustrcmp(wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_lang, "zht"))
bWikiIsTC = true;
else
bWikiIsTC = false;
if (!ustrcmp(wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_lang, "ko"))
bWikiIsKorean = true;
else
bWikiIsKorean = false;
if (!ustrcmp(wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_lang, "da"))
bWikiIsDanish = true;
else
bWikiIsDanish = false;
default_keyboard = wiki_list[aActiveWikis[nCurrentWiki].WikiInfoIdx].wiki_default_keyboard;
fd = file_open(WIKI_INI_NAME, FILE_OPEN_WRITE);
if (fd < 0)
{
fd = file_create(WIKI_INI_NAME, FILE_OPEN_WRITE);
}
if (fd >= 0)
{
char sWikiId[10];
sprintf(sWikiId, "%d", get_wiki_serial_id_from_idx(nCurrentWiki));
wiki_ini_insert_keypair("wiki_id", sWikiId);
debug_printf("write to: %s = '%s'\n", WIKI_INI_NAME, pWikiIni);
bool write_eol = true;
unsigned int i;
for (i = 0; i < lenWikiIni; i++)
{
if (pWikiIni[i] == '\0')
{
if(write_eol)
{
file_write(fd, "\n", 1);
write_eol = false;
}
}
else
{
file_write(fd, &pWikiIni[i], 1);
write_eol = true;
}
}
if (write_eol)
{
file_write(fd, "\n", 1);
}
file_close(fd);
}
else
{
debug_printf("%s failed\n", WIKI_INI_NAME);
}
}
void nls_replace_text(const unsigned char *replace_str, unsigned char *out_str)
{
if (!ustrcmp(replace_str, "title"))
{
extract_title_from_article(NULL, out_str);
while (*out_str)
{
if (*out_str == ' ')
*out_str = '_';
out_str++;
}
}
else
{
ustrcpy(out_str, replace_str);
}
}
WIKI_LICENSE_DRAW *wiki_license_draw()
{
int wiki_idx = get_wiki_idx_from_id(current_article_wiki_id);
int nTempCurrentWiki = nCurrentWiki;
int y = 0;
int x = 0;
unsigned char draw_buf[MAX_LICENSE_TEXT_PIXEL_LINES * LCD_BUF_WIDTH_BYTES];
const unsigned char *pLicenseText;
unsigned char footer_buffer[40];
unsigned char *footer = footer_buffer;
unsigned char sLicenseTextSegment[MAX_LICENSE_TEXT_LEN];
const unsigned char *pLicenseTextSegment;
int line_height = pcfFonts[LICENSE_TEXT_FONT - 1].Fmetrics.linespace;
unsigned char str[256]; // possible buffer overflow
const unsigned char *p, *q;
int bInLink = 0;
int nLinkArticleId = 0;
int width;
int start_x, start_y, end_x, end_y;
int i;
if (wiki_idx >= 0)
nCurrentWiki = wiki_idx;
pLicenseText = get_nls_text("license_text");
memset(footer_buffer, '\0', sizeof(footer_buffer));
memset(footer_buffer, ' ', 5);
int fd = file_open(get_wiki_file_path(nCurrentWiki, "wiki.ftr"), FILE_OPEN_READ);
if (fd >= 0)
{
unsigned char c = ' ';
unsigned char *p = &footer_buffer[5];
while (' ' == c) {
file_read(fd, &c, sizeof(c));
}
while (c >= ' ' && p < &footer_buffer[sizeof(footer_buffer) - 1]) {
*p++ = c;
file_read(fd, &c, sizeof(c));
}
file_close(fd);
}
pWikiLicenseDraw->link_count = 0;
memset(draw_buf, 0, sizeof(draw_buf));
sLicenseTextSegment[0] = '\0';
pLicenseTextSegment = sLicenseTextSegment;
while (*pLicenseText && y < MAX_LICENSE_TEXT_PIXEL_LINES)
{
if (!*pLicenseTextSegment)
{
if (pLicenseText[0] == LICENSE_LINK_START)
{
bInLink = 1;
nLinkArticleId++;
pLicenseText++;
if ((p = ustrchr(pLicenseText, LICENSE_LINK_END)))
{
memcpy(sLicenseTextSegment, pLicenseText, p - pLicenseText);
sLicenseTextSegment[p - pLicenseText] = '\0';
pLicenseText = p + 1;
}
else
{
ustrcpy(sLicenseTextSegment, pLicenseText);
pLicenseText += ustrlen(pLicenseText);
}
}
else if (pLicenseText[0] == NLS_TEXT_REPLACEMENT_START)
{
bInLink = 0;
pLicenseText++;
if ((p = ustrchr(pLicenseText, NLS_TEXT_REPLACEMENT_END)))
{
memcpy(str, pLicenseText, p - pLicenseText);
str[p - pLicenseText] = '\0';
pLicenseText = p + 1;
}
else
{
ustrcpy(str, pLicenseText);
pLicenseText += ustrlen(pLicenseText);
}
nls_replace_text(str, sLicenseTextSegment);
}
else
{
bInLink = 0;
p = ustrchr(pLicenseText, LICENSE_LINK_START);
q = ustrchr(pLicenseText, NLS_TEXT_REPLACEMENT_START);
if ((p && q && p > q) || (!p))
p = q;
if (p)
{
memcpy(sLicenseTextSegment, pLicenseText, p - pLicenseText);
sLicenseTextSegment[p - pLicenseText] = '\0';
pLicenseText = p;
}
else
{
ustrcpy(sLicenseTextSegment, pLicenseText);
pLicenseText += ustrlen(pLicenseText);
}
}
pLicenseTextSegment = sLicenseTextSegment;
}
while (*pLicenseTextSegment && y < MAX_LICENSE_TEXT_PIXEL_LINES)
{
if (!x)
{
while (*pLicenseTextSegment == ' ')
pLicenseTextSegment++;
}
width = extract_str_fitting_width(&pLicenseTextSegment, str, LCD_BUF_WIDTH_PIXELS - x - LCD_LEFT_MARGIN, LICENSE_TEXT_FONT);
if (*str) // if null string, the next segment will start from a new line
{
p = str;
buf_draw_UTF8_str_in_copy_buffer(draw_buf, &p, x, LCD_BUF_WIDTH_PIXELS,
y, y + line_height - 1, LCD_LEFT_MARGIN, LICENSE_TEXT_FONT);
if (bInLink && pWikiLicenseDraw->link_count < MAX_LINKS_IN_LICENSE_TEXT)
{
start_x = x;
start_y = y + 4; // for sync with the links in article text
end_x = x + width;
end_y = y + line_height + 3;
pWikiLicenseDraw->links[pWikiLicenseDraw->link_count].start_xy = (unsigned long)(start_x | (start_y << 8));
pWikiLicenseDraw->links[pWikiLicenseDraw->link_count].end_xy = (unsigned long)(end_x | (end_y << 8));
pWikiLicenseDraw->links[pWikiLicenseDraw->link_count++].article_id = nLinkArticleId;
for(i = start_x + LCD_LEFT_MARGIN; i < end_x + LCD_LEFT_MARGIN; i++)
{
guilib_buffer_set_pixel(draw_buf, i, end_y - 1);
}
}
}
if (*pLicenseTextSegment)
{
x = 0;
y += line_height;
}
else
x += width;
}
if ('\0' == *pLicenseText && NULL != footer) {
pLicenseText = footer;
footer = NULL;
}
}
if (x)
y += line_height;
y += SPACE_AFTER_LICENSE_TEXT;
pWikiLicenseDraw->lines = y;
pWikiLicenseDraw->buf = memory_allocate(y * LCD_BUF_WIDTH_BYTES, "wikinfo5");
memcpy(pWikiLicenseDraw->buf, draw_buf, y * LCD_BUF_WIDTH_BYTES);
nCurrentWiki = nTempCurrentWiki;
return pWikiLicenseDraw;
}
Jump to Line
Something went wrong with that request. Please try again.