New makefile solution: A single invocation of 'make' to build the entire tree. Fully...
[kugel-rb.git] / apps / plugins / dict.c
blob0f7546394683033d5608afe8eca90b03fac9c324
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Tomas Salfischberger
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
24 PLUGIN_HEADER
26 /* save the plugin api pointer. */
27 static const struct plugin_api* rb;
28 /* screen info */
29 static int display_columns, display_lines;
31 /* Some lenghts */
32 #define WORDLEN 32 /* has to be the same in rdf2binary.c */
34 /* Struct packing */
35 #ifdef __GNUC__
36 #define STRUCT_PACKED __attribute__((packed))
37 #else
38 #define STRUCT_PACKED
39 #pragma pack (push, 2)
40 #endif
42 /* The word struct :) */
43 struct stWord
45 char word[WORDLEN];
46 long offset;
47 } STRUCT_PACKED;
49 /* A funtion to get width and height etc (from viewer.c) */
50 void init_screen(void)
52 #ifdef HAVE_LCD_BITMAP
53 int w,h;
55 rb->lcd_getstringsize("o", &w, &h);
56 display_lines = LCD_HEIGHT / h;
57 display_columns = LCD_WIDTH / w;
58 #else
60 display_lines = 2;
61 display_columns = 11;
62 #endif
65 /* global vars for pl_malloc() */
66 void *bufptr;
67 ssize_t bufleft;
69 /* simple function to "allocate" memory in pluginbuffer. */
70 void *pl_malloc(ssize_t size)
72 void *ptr;
73 ptr = bufptr;
75 if (bufleft < size)
77 return NULL;
79 else
81 bufptr += size;
82 bufleft -= size;
83 return ptr;
87 /* init function for pl_malloc() */
88 void pl_malloc_init(void)
90 bufptr = rb->plugin_get_buffer((size_t *)&bufleft);
93 /* for endian problems */
94 #ifdef ROCKBOX_BIG_ENDIAN
95 #define reverse(x) x
96 #else
97 long reverse (long N) {
98 unsigned char B[4];
99 B[0] = (N & 0x000000FF) >> 0;
100 B[1] = (N & 0x0000FF00) >> 8;
101 B[2] = (N & 0x00FF0000) >> 16;
102 B[3] = (N & 0xFF000000) >> 24;
103 return ((B[0] << 24) | (B[1] << 16) | (B[2] << 8) | (B[3] << 0));
105 #endif
107 /* Button definitions */
108 #if CONFIG_KEYPAD == PLAYER_PAD
109 #define LP_QUIT BUTTON_STOP
110 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
111 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
112 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
113 #define LP_QUIT BUTTON_MENU
114 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
115 #define LP_QUIT BUTTON_PLAY
116 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
117 #define LP_QUIT BUTTON_POWER
118 #elif CONFIG_KEYPAD == GIGABEAT_PAD
119 #define LP_QUIT BUTTON_POWER
120 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
121 (CONFIG_KEYPAD == SANSA_C200_PAD)
122 #define LP_QUIT BUTTON_POWER
123 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
124 #define LP_QUIT BUTTON_POWER
125 #elif CONFIG_KEYPAD == MROBE500_PAD
126 #define LP_QUIT BUTTON_POWER
127 #elif CONFIG_KEYPAD == MROBE100_PAD
128 #define LP_QUIT BUTTON_POWER
129 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
130 #define LP_QUIT BUTTON_BACK
131 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
132 #define LP_QUIT BUTTON_RC_REC
133 #elif CONFIG_KEYPAD == COWOND2_PAD
134 #define LP_QUIT BUTTON_POWER
135 #elif CONFIG_KEYPAD == IAUDIO67_PAD
136 #define LP_QUIT BUTTON_POWER
137 #else
138 #define LP_QUIT BUTTON_OFF
139 #endif
141 /* data files */
142 #define DICT_INDEX ROCKBOX_DIR "/rocks/apps/dict.index"
143 #define DICT_DESC ROCKBOX_DIR "/rocks/apps/dict.desc"
145 /* the main plugin function */
146 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
148 char searchword[WORDLEN]; /* word to search for */
149 char *description; /* pointer to description buffer */
150 char *output; /* pointer to output buffer */
151 char *ptr, *space;
152 struct stWord word; /* the struct to read into */
153 int fIndex, fData; /* files */
154 int filesize, high, low, probe;
155 int lines, len, outputted, next;
157 /* plugin stuff */
158 (void)parameter;
159 rb = api;
161 /* get screen info */
162 init_screen();
164 /* get pl_malloc() buffer ready. */
165 pl_malloc_init();
167 /* init description buffer (size is because we don't have scrolling)*/
168 description = (char *)pl_malloc(display_columns * display_lines);
169 if (description == NULL)
171 DEBUGF("Err: failed to allocate description buffer.");
172 return PLUGIN_ERROR;
175 /* init output buffer */
176 output = (char *)pl_malloc(display_columns);
177 if (output == NULL)
179 DEBUGF("Err: failed to allocate output buffer.");
180 return PLUGIN_ERROR;
183 /* "clear" input buffer */
184 searchword[0] = '\0';
186 rb->kbd_input(searchword, sizeof(searchword)); /* get the word to search */
188 fIndex = rb->open(DICT_INDEX, O_RDONLY); /* index file */
189 if (fIndex < 0)
191 DEBUGF("Err: Failed to open index file.\n");
192 rb->splash(HZ*2, "Failed to open index.");
193 return PLUGIN_ERROR;
196 filesize = rb->filesize(fIndex); /* get filesize */
198 DEBUGF("Filesize: %d bytes = %d words \n", filesize,
199 (filesize / (int)sizeof(struct stWord)));
201 /* for the searching algorithm */
202 high = filesize / sizeof( struct stWord );
203 low = -1;
205 while (high - low > 1)
207 probe = (high + low) / 2;
209 /* Jump to word pointed by probe, and read it. */
210 rb->lseek(fIndex, sizeof(struct stWord) * probe, SEEK_SET);
211 rb->read(fIndex, &word, sizeof(struct stWord));
213 /* jump according to the found word. */
214 if (rb->strcasecmp(searchword, word.word) < 0)
216 high = probe;
218 else
220 low = probe;
224 /* read in the word */
225 rb->lseek(fIndex, sizeof(struct stWord) * low, SEEK_SET);
226 rb->read(fIndex, &word, sizeof(struct stWord));
228 /* Check if we found something */
229 if (low == -1 || rb->strcasecmp(searchword, word.word) != 0)
231 DEBUGF("Not found.\n");
232 rb->splash(HZ*2, "Not found.");
233 rb->close(fIndex);
234 return PLUGIN_OK;
237 DEBUGF("Found %s at offset %ld\n", word.word, reverse(word.offset));
239 /* now open the description file */
240 fData = rb->open(DICT_DESC, O_RDONLY);
241 if (fData < 0)
243 DEBUGF("Err: Failed to open description file.\n");
244 rb->splash(HZ*2, "Failed to open descriptions.");
245 rb->close(fIndex);
246 return PLUGIN_ERROR;
249 /* seek to the right offset */
250 rb->lseek(fData, (off_t)reverse(word.offset), SEEK_SET);
252 /* Read in the description */
253 rb->read_line(fData, description, display_columns * display_lines);
255 /* And print it to debug. */
256 DEBUGF("Description: %s\n", description);
258 /* get pointer to first char */
259 ptr = description;
261 lines = 0;
262 outputted = 0;
263 len = rb->strlen(description);
265 /* clear screen */
266 rb->lcd_clear_display();
268 /* for large screens display the searched word. */
269 if(display_lines > 4)
271 rb->lcd_puts(0, lines, searchword);
272 lines++;
275 /* TODO: Scroll, or just stop when there are to much lines. */
276 while (1)
278 /* copy one lcd line */
279 rb->strncpy(output, ptr, display_columns);
280 output[display_columns] = '\0';
282 /* typecast to kill a warning... */
283 if((int)rb->strlen(ptr) < display_columns)
285 rb->lcd_puts(0, lines, output);
286 lines++;
287 break;
291 /* get the last spacechar */
292 space = rb->strrchr(output, ' ');
294 if (space != NULL)
296 *space = '\0';
297 next = (space - (char*)output) + 1;
299 else
301 next = display_columns;
304 /* put the line on screen */
305 rb->lcd_puts(0, lines, output);
307 /* get output count */
308 outputted += rb->strlen(output);
310 if (outputted < len)
312 /* set pointer to the next part */
313 ptr += next;
314 lines++;
316 else
318 break;
321 rb->lcd_update();
323 /* wait for keypress */
324 while(rb->button_get(true) != LP_QUIT)
326 /* do nothing */
327 /* maybe define some keys for navigation here someday. */
330 rb->close(fIndex);
331 rb->close(fData);
332 return PLUGIN_OK;