summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2006-05-20 10:16:03 +0000
committerDave Chapman <dave@dchapman.com>2006-05-20 10:16:03 +0000
commit4c3ada442817ab313c5737861fd80895f9ee6e3b (patch)
tree0b2410612f6bc4ad3252c84a684ff0aa83f6cbdc
parentfa5caa0b5b2bce6ec56a99d716584405854ede76 (diff)
downloadrockbox-4c3ada442817ab313c5737861fd80895f9ee6e3b.tar.gz
rockbox-4c3ada442817ab313c5737861fd80895f9ee6e3b.zip
Patch #5374 - Updated text editor plugin from Jonathan Gordon.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9963 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/text_editor.c310
1 files changed, 185 insertions, 125 deletions
diff --git a/apps/plugins/text_editor.c b/apps/plugins/text_editor.c
index 89fdc39f90..450155e180 100644
--- a/apps/plugins/text_editor.c
+++ b/apps/plugins/text_editor.c
@@ -50,121 +50,156 @@
50#define TEXT_EDITOR_CANCEL BUTTON_POWER 50#define TEXT_EDITOR_CANCEL BUTTON_POWER
51#define TEXT_EDITOR_ITEM_MENU BUTTON_PLAY 51#define TEXT_EDITOR_ITEM_MENU BUTTON_PLAY
52 52
53#elif CONFIG_KEYPAD == GIGABEAT_PAD
54
55#else 53#else
56 #error TEXT_EDITOR: Unsupported keypad 54 #error TEXT_EDITOR: Unsupported keypad
57#endif 55#endif
58 56
59#define MAX_LINE_LEN 128
60 57
61#if PLUGIN_BUFFER_SIZE > 0x45000 58#if PLUGIN_BUFFER_SIZE > 0x45000
62#define MAX_LINES 2048 59#define MAX_CHARS 0x40000 /* 128 kiB */
63#else 60#else
64#define MAX_LINES 128 61#define MAX_CHARS 0x6000 /* 24 kiB */
65#endif 62#endif
66 63#define MAX_LINE_LEN 2048
67PLUGIN_HEADER 64PLUGIN_HEADER
68static struct plugin_api* rb; 65static struct plugin_api* rb;
69 66
70struct LineStruct { 67static char buffer[MAX_CHARS];
71 char line[MAX_LINE_LEN]; 68static char eol[3];
72 int prev; /* index to prev item, or -1 */ 69static int char_count = 0;
73 int next; /* index to next item, or -1 */ 70static int line_count = 0;
74}; 71static int last_action_line = 0;
72static int last_char_index = 0;
73
74#define ACTION_INSERT 0
75#define ACTION_GET 1
76#define ACTION_REMOVE 2
77#define ACTION_UPDATE 3
78#define ACTION_CONCAT 4
79
80int _do_action(int action, char* str, int line);
81#ifndef HAVE_ADJUSTABLE_CPU_FREQ
82#define do_action _do_action
83#else
84int do_action(int action, char* str, int line)
85{
86 int r;
87 rb->cpu_boost(1);
88 r = _do_action(action,str,line);
89 rb->cpu_boost(0);
90 return r;
91}
92#endif
75 93
76struct LineStruct lines[MAX_LINES]; 94int _do_action(int action, char* str, int line)
77int line_count = 0;
78int first = -1, last = -1;
79int indicies[MAX_LINES];
80/**************************** stuff for the linked lists ***************/
81int build_indicies(void)
82{ 95{
83 int i=0, index = first; 96 int len;
84 struct LineStruct *line; 97 int i=0,c=0;
85 if (first==-1) 98 if (line>=last_action_line)
86 return 0;
87 while (i<line_count)
88 { 99 {
89 indicies[i++] = index; 100 i = last_action_line;
90 DEBUGF("%d,",index); 101 c = last_char_index;
91 line = &lines[index]; 102 }
92 index = line->next; 103 while (i<line && i<line_count)
93 104 {
105 c += rb->strlen(&buffer[c])+1;
106 i++;
107 }
108 switch (action)
109 {
110 case ACTION_INSERT:
111 len = rb->strlen(str)+1;
112 if ( char_count+ len > MAX_CHARS )
113 return 0;
114 rb->memmove(&buffer[c+len],&buffer[c],char_count);
115 rb->strcpy(&buffer[c],str);
116 char_count += len;
117 line_count++;
118 break;
119 case ACTION_GET:
120 if (line > line_count)
121 return 0;
122 last_action_line = i;
123 last_char_index = c;
124 return c;
125 break;
126 case ACTION_REMOVE:
127 if (line > line_count)
128 return 0;
129 len = rb->strlen(&buffer[c])+1;
130 rb->memmove(&buffer[c],&buffer[c+len],char_count);
131 char_count -= len;
132 line_count--;
133 break;
134 case ACTION_UPDATE:
135 if (line > line_count)
136 return 0;
137 len = rb->strlen(&buffer[c])+1;
138 rb->memmove(&buffer[c+rb->strlen(str)+1],&buffer[c+len],char_count);
139 rb->strcpy(&buffer[c],str);
140 char_count += rb->strlen(str)+1-len;
141 break;
142 case ACTION_CONCAT:
143 if (line > line_count)
144 return 0;
145 rb->memmove(&buffer[c-1],&buffer[c],char_count);
146 break;
147 default:
148 return 0;
94 } 149 }
95 DEBUGF("\n"); 150 last_action_line = i;
151 last_char_index = c;
96 return 1; 152 return 1;
97} 153}
98 154char *list_get_name_cb(int selected_item,void* data,char* buf)
99int find_first_free(int start)
100{ 155{
101 int i; 156 char *b = &buffer[do_action(ACTION_GET,0,selected_item)];
102 if ((start <0) || (start >=MAX_LINES)) 157 (void)data;
103 start = 0; 158 if (rb->strlen(b) >= MAX_PATH)
104 i = start;
105 do
106 { 159 {
107 if (lines[i].line[0] == '\0') 160 char t = b[MAX_PATH-10];
108 return i; 161 b[MAX_PATH-10] = '\0';
109 i = (i+1)%MAX_LINES; 162 rb->snprintf(buf,MAX_PATH,"%s ...\0",b);
110 } while (i!=start); 163 b[MAX_PATH-10] = t;
111 return -1; 164 }
165 else rb->strcpy(buf,b);
166 return buf;
112} 167}
113 168char filename[MAX_PATH];
114int add_line(char *line, int idx_after_me) 169int get_eol_string(char* fn)
115{ 170{
116 struct LineStruct *temp; 171 int fd=-1;
117 int next; 172 char t;
118 int this_idx = find_first_free(idx_after_me); 173 if (!fn)
119 if ((line_count >= MAX_LINES) || (this_idx == -1)) 174 return 0;
120 return -1; 175 else if (!fn[0])
121 DEBUGF("line:%s ,idx_after_me=%d\n",line,idx_after_me); 176 return 0;
122 if (idx_after_me == -1) /* add as the first item */ 177 fd = rb->PREFIX(open(fn,O_RDONLY));
178 if (fd<0)
179 return 0;
180 eol[0] = '\0';
181 while (!eol[0])
123 { 182 {
124 rb->strcpy(lines[this_idx].line,line); 183 if (!rb->read(fd,&t,1))
125 lines[this_idx].prev = -1; 184 {
126 if (first != -1) 185 rb->strcpy(eol,"\n");
127 lines[first].prev = this_idx; 186 return 0;
128 lines[this_idx].next = first; 187 }
129 first = this_idx; 188 if (t == '\r')
130 if (last == idx_after_me) 189 {
131 last = this_idx; 190 if (rb->read(fd,&t,1) && t=='\n')
132 line_count++; 191 rb->strcpy(eol,"\r\n");
133 return 1; 192 else rb->strcpy(eol,"\r");
193 }
194 else if (t == '\n')
195 {
196 rb->strcpy(eol,"\n");
197 }
134 } 198 }
135 199 rb->close(fd);
136 temp = &lines[idx_after_me]; 200 return 1;
137 next = lines[idx_after_me].next;
138 temp->next = this_idx;
139 rb->strcpy(lines[this_idx].line,line);
140 temp = &lines[this_idx];
141 temp->next = next;
142 temp->prev = idx_after_me;
143 if (last == idx_after_me)
144 last = this_idx;
145 if (first == -1)
146 first = this_idx;
147 line_count ++;
148 return this_idx;
149} 201}
150 202
151void del_line(int line)
152{
153 int idx_prev, idx_next;
154 idx_prev = (&lines[line])->prev;
155 idx_next = (&lines[line])->next;
156 lines[line].line[0] = '\0';
157 lines[idx_prev].next = idx_next;
158 lines[idx_next].prev = idx_prev;
159 line_count --;
160}
161char *list_get_name_cb(int selected_item,void* data,char* buf)
162{
163 (void)data;
164 rb->strcpy(buf,lines[indicies[selected_item]].line);
165 return buf;
166}
167char filename[1024];
168void save_changes(int overwrite) 203void save_changes(int overwrite)
169{ 204{
170 int fd; 205 int fd;
@@ -173,34 +208,37 @@ void save_changes(int overwrite)
173 if (!filename[0] || !overwrite) 208 if (!filename[0] || !overwrite)
174 { 209 {
175 rb->strcpy(filename,"/"); 210 rb->strcpy(filename,"/");
176 rb->kbd_input(filename,1024); 211 rb->kbd_input(filename,MAX_PATH);
177 } 212 }
178 213
179 fd = rb->open(filename,O_WRONLY|O_CREAT); 214 fd = rb->open(filename,O_WRONLY|O_CREAT);
180 if (!fd) 215 if (fd < 0)
181 { 216 {
182 rb->splash(HZ*2,1,"Changes NOT saved"); 217 rb->splash(HZ*2,1,"Changes NOT saved");
183 return; 218 return;
184 } 219 }
185 220
186 rb->lcd_clear_display(); 221 rb->lcd_clear_display();
187 build_indicies(); 222#ifdef HAVE_ADJUSTABLE_CPU_FREQ
223 rb->cpu_boost(1);
224#endif
188 for (i=0;i<line_count;i++) 225 for (i=0;i<line_count;i++)
189 { 226 {
190 rb->fdprintf(fd,"%s\n",lines[indicies[i]].line); 227 rb->fdprintf(fd,"%s%s",&buffer[do_action(ACTION_GET,0,i)],eol);
191 } 228 }
192 229#ifdef HAVE_ADJUSTABLE_CPU_FREQ
230 rb->cpu_boost(0);
231#endif
193 rb->close(fd); 232 rb->close(fd);
194} 233}
195 234
196void setup_lists(struct gui_synclist *lists) 235void setup_lists(struct gui_synclist *lists, int sel)
197{ 236{
198 build_indicies();
199 rb->gui_synclist_init(lists,list_get_name_cb,0); 237 rb->gui_synclist_init(lists,list_get_name_cb,0);
200 rb->gui_synclist_set_icon_callback(lists,NULL); 238 rb->gui_synclist_set_icon_callback(lists,NULL);
201 rb->gui_synclist_set_nb_items(lists,line_count); 239 rb->gui_synclist_set_nb_items(lists,line_count);
202 rb->gui_synclist_limit_scroll(lists,true); 240 rb->gui_synclist_limit_scroll(lists,true);
203 rb->gui_synclist_select_item(lists, 0); 241 rb->gui_synclist_select_item(lists, sel);
204 rb->gui_synclist_draw(lists); 242 rb->gui_synclist_draw(lists);
205} 243}
206enum { 244enum {
@@ -219,7 +257,6 @@ int do_item_menu(int cur_sel, char* copy_buffer)
219 { "Insert Below", NULL }, 257 { "Insert Below", NULL },
220 { "", NULL }, 258 { "", NULL },
221 { "Cat To Above",NULL }, 259 { "Cat To Above",NULL },
222 /* { "Split Line",NULL }, */
223 { "", NULL }, 260 { "", NULL },
224 { "Save", NULL }, 261 { "Save", NULL },
225 }; 262 };
@@ -229,12 +266,12 @@ int do_item_menu(int cur_sel, char* copy_buffer)
229 switch (rb->menu_show(m)) 266 switch (rb->menu_show(m))
230 { 267 {
231 case 0: /* cut */ 268 case 0: /* cut */
232 rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line); 269 rb->strcpy(copy_buffer,&buffer[do_action(ACTION_GET,0,cur_sel)]);
233 del_line(indicies[cur_sel]); 270 do_action(ACTION_REMOVE,0,cur_sel);
234 ret = MENU_RET_UPDATE; 271 ret = MENU_RET_UPDATE;
235 break; 272 break;
236 case 1: /* copy */ 273 case 1: /* copy */
237 rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line); 274 rb->strcpy(copy_buffer,&buffer[do_action(ACTION_GET,0,cur_sel)]);
238 ret = MENU_RET_NO_UPDATE; 275 ret = MENU_RET_NO_UPDATE;
239 break; 276 break;
240 case 2: /* blank */ 277 case 2: /* blank */
@@ -244,7 +281,7 @@ int do_item_menu(int cur_sel, char* copy_buffer)
244 case 3: /* insert above */ 281 case 3: /* insert above */
245 if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN)) 282 if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN))
246 { 283 {
247 add_line(copy_buffer,lines[indicies[cur_sel]].prev); 284 do_action(ACTION_INSERT,copy_buffer,cur_sel);
248 copy_buffer[0]='\0'; 285 copy_buffer[0]='\0';
249 ret = MENU_RET_UPDATE; 286 ret = MENU_RET_UPDATE;
250 } 287 }
@@ -252,7 +289,7 @@ int do_item_menu(int cur_sel, char* copy_buffer)
252 case 4: /* insert below */ 289 case 4: /* insert below */
253 if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN)) 290 if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN))
254 { 291 {
255 add_line(copy_buffer,indicies[cur_sel]); 292 do_action(ACTION_INSERT,copy_buffer,cur_sel+1);
256 copy_buffer[0]='\0'; 293 copy_buffer[0]='\0';
257 ret = MENU_RET_UPDATE; 294 ret = MENU_RET_UPDATE;
258 } 295 }
@@ -263,13 +300,10 @@ int do_item_menu(int cur_sel, char* copy_buffer)
263 case 6: /* cat to above */ 300 case 6: /* cat to above */
264 if (cur_sel>0) 301 if (cur_sel>0)
265 { 302 {
266 rb->strcat(lines[indicies[cur_sel-1]].line,lines[indicies[cur_sel]].line); 303 do_action(ACTION_CONCAT,0,cur_sel);
267 del_line(indicies[cur_sel]);
268 ret = MENU_RET_UPDATE; 304 ret = MENU_RET_UPDATE;
269 } 305 }
270 break; 306 break;
271 /* case 7: // split line */
272
273 case 7: /* save */ 307 case 7: /* save */
274 ret = MENU_RET_SAVE; 308 ret = MENU_RET_SAVE;
275 break; 309 break;
@@ -284,19 +318,32 @@ int do_item_menu(int cur_sel, char* copy_buffer)
284enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 318enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
285{ 319{
286 int fd; 320 int fd;
287 char temp_line[MAX_LINE_LEN]; 321 static char temp_line[MAX_LINE_LEN];
288 322
289 struct gui_synclist lists; 323 struct gui_synclist lists;
290 bool exit = false; 324 bool exit = false;
291 int button, last_button = BUTTON_NONE; 325 int button, last_button = BUTTON_NONE;
292 bool changed = false; 326 bool changed = false;
293 int cur_sel; 327 int cur_sel=0;
294 char copy_buffer[MAX_LINE_LEN]; copy_buffer[0]='\0'; 328 static char copy_buffer[MAX_LINE_LEN];
329 bool prev_show_statusbar;
295 330
296 rb = api; 331 rb = api;
332
333 copy_buffer[0]='\0';
334 prev_show_statusbar = rb->global_settings->statusbar;
335 rb->global_settings->statusbar = false;
336
337#ifdef HAVE_ADJUSTABLE_CPU_FREQ
338 rb->cpu_boost(1);
339#endif
297 if (parameter) 340 if (parameter)
298 { 341 {
299 rb->strcpy(filename,(char*)parameter); 342 rb->strcpy(filename,(char*)parameter);
343 if (!get_eol_string(filename))
344 {
345 rb->strcpy(eol,"\n");
346 }
300 fd = rb->open(filename,O_RDONLY); 347 fd = rb->open(filename,O_RDONLY);
301 if (fd<0) 348 if (fd<0)
302 { 349 {
@@ -306,7 +353,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
306 /* read in the file */ 353 /* read in the file */
307 while (rb->read_line(fd,temp_line,MAX_LINE_LEN)) 354 while (rb->read_line(fd,temp_line,MAX_LINE_LEN))
308 { 355 {
309 if (add_line(temp_line,last) < 0) 356 if (!do_action(ACTION_INSERT,temp_line,line_count))
310 { 357 {
311 rb->splash(HZ*2,true,"Error reading file: %s",(char*)parameter); 358 rb->splash(HZ*2,true,"Error reading file: %s",(char*)parameter);
312 rb->close(fd); 359 rb->close(fd);
@@ -315,16 +362,30 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
315 } 362 }
316 rb->close(fd); 363 rb->close(fd);
317 } 364 }
318 else filename[0] = '\0'; 365 else
366 {
367 filename[0] = '\0';
368 rb->strcpy(eol,"\n");
369 }
370#ifdef HAVE_ADJUSTABLE_CPU_FREQ
371 rb->cpu_boost(0);
372#endif
319 /* now dump it in the list */ 373 /* now dump it in the list */
320 setup_lists(&lists); 374 setup_lists(&lists,0);
375 rb->lcd_update();
321 while (!exit) 376 while (!exit)
322 { 377 {
378#ifdef HAVE_ADJUSTABLE_CPU_FREQ
379 rb->cpu_boost(1);
380#endif
323 rb->gui_synclist_draw(&lists); 381 rb->gui_synclist_draw(&lists);
324 cur_sel = rb->gui_synclist_get_sel_pos(&lists); 382 cur_sel = rb->gui_synclist_get_sel_pos(&lists);
325 button = rb->button_get(true); 383 button = rb->button_get(true);
326 if (rb->gui_synclist_do_button(&lists,button)) 384 if (rb->gui_synclist_do_button(&lists,button))
327 continue; 385 continue;
386#ifdef HAVE_ADJUSTABLE_CPU_FREQ
387 rb->cpu_boost(0);
388#endif
328 switch (button) 389 switch (button)
329 { 390 {
330 case TEXT_EDITOR_SELECT: 391 case TEXT_EDITOR_SELECT:
@@ -333,15 +394,15 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
333 if (last_button != TEXT_EDITOR_SELECT_PRE) 394 if (last_button != TEXT_EDITOR_SELECT_PRE)
334 break; 395 break;
335#endif 396#endif
336 char buf[MAX_LINE_LEN];buf[0]='\0';
337
338 if (line_count) 397 if (line_count)
339 rb->strcpy(buf,lines[indicies[cur_sel]].line); 398 rb->strcpy(temp_line,&buffer[do_action(ACTION_GET,0,cur_sel)]);
340 if (!rb->kbd_input(buf,MAX_LINE_LEN)) 399 if (!rb->kbd_input(temp_line,MAX_LINE_LEN))
341 { 400 {
342 if (line_count) 401 if (line_count)
343 rb->strcpy(lines[indicies[cur_sel]].line,buf); 402 {
344 else { add_line(buf, first); setup_lists(&lists); } 403 do_action(ACTION_UPDATE,temp_line,cur_sel);
404 }
405 else do_action(ACTION_INSERT,temp_line,cur_sel);
345 changed = true; 406 changed = true;
346 } 407 }
347 } 408 }
@@ -353,10 +414,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
353 break; 414 break;
354#endif 415#endif
355 if (!line_count) break; 416 if (!line_count) break;
356 rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line); 417 rb->strcpy(copy_buffer,&buffer[do_action(ACTION_GET,0,cur_sel)]);
357 del_line(indicies[cur_sel]); 418 do_action(ACTION_REMOVE,0,cur_sel);
358 changed = true; 419 changed = true;
359 setup_lists(&lists);
360 break; 420 break;
361#endif 421#endif
362#ifdef TEXT_EDITOR_ITEM_MENU 422#ifdef TEXT_EDITOR_ITEM_MENU
@@ -381,7 +441,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
381 break; 441 break;
382 case MENU_RET_UPDATE: 442 case MENU_RET_UPDATE:
383 changed = true; 443 changed = true;
384 setup_lists(&lists);
385 break; 444 break;
386 case MENU_RET_NO_UPDATE: 445 case MENU_RET_NO_UPDATE:
387 break; 446 break;
@@ -441,7 +500,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
441 break; 500 break;
442 } 501 }
443 last_button = button; 502 last_button = button;
503 rb->gui_synclist_set_nb_items(&lists,line_count);
444 } 504 }
445 505 rb->global_settings->statusbar = prev_show_statusbar;
446 return PLUGIN_OK; 506 return PLUGIN_OK;
447} 507}