From 4c3ada442817ab313c5737861fd80895f9ee6e3b Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Sat, 20 May 2006 10:16:03 +0000 Subject: [PATCH] Patch #5374 - Updated text editor plugin from Jonathan Gordon. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9963 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/text_editor.c | 316 ++++++++++++++++++++++--------------- 1 file changed, 188 insertions(+), 128 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 @@ #define TEXT_EDITOR_CANCEL BUTTON_POWER #define TEXT_EDITOR_ITEM_MENU BUTTON_PLAY -#elif CONFIG_KEYPAD == GIGABEAT_PAD - #else #error TEXT_EDITOR: Unsupported keypad #endif -#define MAX_LINE_LEN 128 #if PLUGIN_BUFFER_SIZE > 0x45000 -#define MAX_LINES 2048 +#define MAX_CHARS 0x40000 /* 128 kiB */ #else -#define MAX_LINES 128 +#define MAX_CHARS 0x6000 /* 24 kiB */ #endif - +#define MAX_LINE_LEN 2048 PLUGIN_HEADER static struct plugin_api* rb; -struct LineStruct { - char line[MAX_LINE_LEN]; - int prev; /* index to prev item, or -1 */ - int next; /* index to next item, or -1 */ -}; +static char buffer[MAX_CHARS]; +static char eol[3]; +static int char_count = 0; +static int line_count = 0; +static int last_action_line = 0; +static int last_char_index = 0; -struct LineStruct lines[MAX_LINES]; -int line_count = 0; -int first = -1, last = -1; -int indicies[MAX_LINES]; -/**************************** stuff for the linked lists ***************/ -int build_indicies(void) +#define ACTION_INSERT 0 +#define ACTION_GET 1 +#define ACTION_REMOVE 2 +#define ACTION_UPDATE 3 +#define ACTION_CONCAT 4 + +int _do_action(int action, char* str, int line); +#ifndef HAVE_ADJUSTABLE_CPU_FREQ +#define do_action _do_action +#else +int do_action(int action, char* str, int line) { - int i=0, index = first; - struct LineStruct *line; - if (first==-1) - return 0; - while (inext; + int r; + rb->cpu_boost(1); + r = _do_action(action,str,line); + rb->cpu_boost(0); + return r; +} +#endif +int _do_action(int action, char* str, int line) +{ + int len; + int i=0,c=0; + if (line>=last_action_line) + { + i = last_action_line; + c = last_char_index; } - DEBUGF("\n"); + while (istrlen(&buffer[c])+1; + i++; + } + switch (action) + { + case ACTION_INSERT: + len = rb->strlen(str)+1; + if ( char_count+ len > MAX_CHARS ) + return 0; + rb->memmove(&buffer[c+len],&buffer[c],char_count); + rb->strcpy(&buffer[c],str); + char_count += len; + line_count++; + break; + case ACTION_GET: + if (line > line_count) + return 0; + last_action_line = i; + last_char_index = c; + return c; + break; + case ACTION_REMOVE: + if (line > line_count) + return 0; + len = rb->strlen(&buffer[c])+1; + rb->memmove(&buffer[c],&buffer[c+len],char_count); + char_count -= len; + line_count--; + break; + case ACTION_UPDATE: + if (line > line_count) + return 0; + len = rb->strlen(&buffer[c])+1; + rb->memmove(&buffer[c+rb->strlen(str)+1],&buffer[c+len],char_count); + rb->strcpy(&buffer[c],str); + char_count += rb->strlen(str)+1-len; + break; + case ACTION_CONCAT: + if (line > line_count) + return 0; + rb->memmove(&buffer[c-1],&buffer[c],char_count); + break; + default: + return 0; + } + last_action_line = i; + last_char_index = c; return 1; } - -int find_first_free(int start) -{ - int i; - if ((start <0) || (start >=MAX_LINES)) - start = 0; - i = start; - do - { - if (lines[i].line[0] == '\0') - return i; - i = (i+1)%MAX_LINES; - } while (i!=start); - return -1; -} - -int add_line(char *line, int idx_after_me) -{ - struct LineStruct *temp; - int next; - int this_idx = find_first_free(idx_after_me); - if ((line_count >= MAX_LINES) || (this_idx == -1)) - return -1; - DEBUGF("line:%s ,idx_after_me=%d\n",line,idx_after_me); - if (idx_after_me == -1) /* add as the first item */ - { - rb->strcpy(lines[this_idx].line,line); - lines[this_idx].prev = -1; - if (first != -1) - lines[first].prev = this_idx; - lines[this_idx].next = first; - first = this_idx; - if (last == idx_after_me) - last = this_idx; - line_count++; - return 1; - } - - temp = &lines[idx_after_me]; - next = lines[idx_after_me].next; - temp->next = this_idx; - rb->strcpy(lines[this_idx].line,line); - temp = &lines[this_idx]; - temp->next = next; - temp->prev = idx_after_me; - if (last == idx_after_me) - last = this_idx; - if (first == -1) - first = this_idx; - line_count ++; - return this_idx; -} - -void del_line(int line) -{ - int idx_prev, idx_next; - idx_prev = (&lines[line])->prev; - idx_next = (&lines[line])->next; - lines[line].line[0] = '\0'; - lines[idx_prev].next = idx_next; - lines[idx_next].prev = idx_prev; - line_count --; -} char *list_get_name_cb(int selected_item,void* data,char* buf) { + char *b = &buffer[do_action(ACTION_GET,0,selected_item)]; (void)data; - rb->strcpy(buf,lines[indicies[selected_item]].line); + if (rb->strlen(b) >= MAX_PATH) + { + char t = b[MAX_PATH-10]; + b[MAX_PATH-10] = '\0'; + rb->snprintf(buf,MAX_PATH,"%s ...\0",b); + b[MAX_PATH-10] = t; + } + else rb->strcpy(buf,b); return buf; } -char filename[1024]; +char filename[MAX_PATH]; +int get_eol_string(char* fn) +{ + int fd=-1; + char t; + if (!fn) + return 0; + else if (!fn[0]) + return 0; + fd = rb->PREFIX(open(fn,O_RDONLY)); + if (fd<0) + return 0; + eol[0] = '\0'; + while (!eol[0]) + { + if (!rb->read(fd,&t,1)) + { + rb->strcpy(eol,"\n"); + return 0; + } + if (t == '\r') + { + if (rb->read(fd,&t,1) && t=='\n') + rb->strcpy(eol,"\r\n"); + else rb->strcpy(eol,"\r"); + } + else if (t == '\n') + { + rb->strcpy(eol,"\n"); + } + } + rb->close(fd); + return 1; +} + void save_changes(int overwrite) { int fd; @@ -173,34 +208,37 @@ void save_changes(int overwrite) if (!filename[0] || !overwrite) { rb->strcpy(filename,"/"); - rb->kbd_input(filename,1024); + rb->kbd_input(filename,MAX_PATH); } fd = rb->open(filename,O_WRONLY|O_CREAT); - if (!fd) + if (fd < 0) { rb->splash(HZ*2,1,"Changes NOT saved"); return; } rb->lcd_clear_display(); - build_indicies(); +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(1); +#endif for (i=0;ifdprintf(fd,"%s\n",lines[indicies[i]].line); + rb->fdprintf(fd,"%s%s",&buffer[do_action(ACTION_GET,0,i)],eol); } - +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(0); +#endif rb->close(fd); } -void setup_lists(struct gui_synclist *lists) +void setup_lists(struct gui_synclist *lists, int sel) { - build_indicies(); rb->gui_synclist_init(lists,list_get_name_cb,0); rb->gui_synclist_set_icon_callback(lists,NULL); rb->gui_synclist_set_nb_items(lists,line_count); rb->gui_synclist_limit_scroll(lists,true); - rb->gui_synclist_select_item(lists, 0); + rb->gui_synclist_select_item(lists, sel); rb->gui_synclist_draw(lists); } enum { @@ -219,7 +257,6 @@ int do_item_menu(int cur_sel, char* copy_buffer) { "Insert Below", NULL }, { "", NULL }, { "Cat To Above",NULL }, - /* { "Split Line",NULL }, */ { "", NULL }, { "Save", NULL }, }; @@ -229,12 +266,12 @@ int do_item_menu(int cur_sel, char* copy_buffer) switch (rb->menu_show(m)) { case 0: /* cut */ - rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line); - del_line(indicies[cur_sel]); + rb->strcpy(copy_buffer,&buffer[do_action(ACTION_GET,0,cur_sel)]); + do_action(ACTION_REMOVE,0,cur_sel); ret = MENU_RET_UPDATE; break; case 1: /* copy */ - rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line); + rb->strcpy(copy_buffer,&buffer[do_action(ACTION_GET,0,cur_sel)]); ret = MENU_RET_NO_UPDATE; break; case 2: /* blank */ @@ -244,7 +281,7 @@ int do_item_menu(int cur_sel, char* copy_buffer) case 3: /* insert above */ if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN)) { - add_line(copy_buffer,lines[indicies[cur_sel]].prev); + do_action(ACTION_INSERT,copy_buffer,cur_sel); copy_buffer[0]='\0'; ret = MENU_RET_UPDATE; } @@ -252,7 +289,7 @@ int do_item_menu(int cur_sel, char* copy_buffer) case 4: /* insert below */ if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN)) { - add_line(copy_buffer,indicies[cur_sel]); + do_action(ACTION_INSERT,copy_buffer,cur_sel+1); copy_buffer[0]='\0'; ret = MENU_RET_UPDATE; } @@ -263,13 +300,10 @@ int do_item_menu(int cur_sel, char* copy_buffer) case 6: /* cat to above */ if (cur_sel>0) { - rb->strcat(lines[indicies[cur_sel-1]].line,lines[indicies[cur_sel]].line); - del_line(indicies[cur_sel]); + do_action(ACTION_CONCAT,0,cur_sel); ret = MENU_RET_UPDATE; } break; - /* case 7: // split line */ - case 7: /* save */ ret = MENU_RET_SAVE; break; @@ -284,19 +318,32 @@ int do_item_menu(int cur_sel, char* copy_buffer) enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { int fd; - char temp_line[MAX_LINE_LEN]; + static char temp_line[MAX_LINE_LEN]; struct gui_synclist lists; bool exit = false; int button, last_button = BUTTON_NONE; bool changed = false; - int cur_sel; - char copy_buffer[MAX_LINE_LEN]; copy_buffer[0]='\0'; + int cur_sel=0; + static char copy_buffer[MAX_LINE_LEN]; + bool prev_show_statusbar; rb = api; + + copy_buffer[0]='\0'; + prev_show_statusbar = rb->global_settings->statusbar; + rb->global_settings->statusbar = false; + +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(1); +#endif if (parameter) { rb->strcpy(filename,(char*)parameter); + if (!get_eol_string(filename)) + { + rb->strcpy(eol,"\n"); + } fd = rb->open(filename,O_RDONLY); if (fd<0) { @@ -306,7 +353,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) /* read in the file */ while (rb->read_line(fd,temp_line,MAX_LINE_LEN)) { - if (add_line(temp_line,last) < 0) + if (!do_action(ACTION_INSERT,temp_line,line_count)) { rb->splash(HZ*2,true,"Error reading file: %s",(char*)parameter); rb->close(fd); @@ -315,16 +362,30 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) } rb->close(fd); } - else filename[0] = '\0'; + else + { + filename[0] = '\0'; + rb->strcpy(eol,"\n"); + } +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(0); +#endif /* now dump it in the list */ - setup_lists(&lists); + setup_lists(&lists,0); + rb->lcd_update(); while (!exit) { +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(1); +#endif rb->gui_synclist_draw(&lists); cur_sel = rb->gui_synclist_get_sel_pos(&lists); button = rb->button_get(true); if (rb->gui_synclist_do_button(&lists,button)) continue; +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(0); +#endif switch (button) { case TEXT_EDITOR_SELECT: @@ -333,15 +394,15 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) if (last_button != TEXT_EDITOR_SELECT_PRE) break; #endif - char buf[MAX_LINE_LEN];buf[0]='\0'; - if (line_count) - rb->strcpy(buf,lines[indicies[cur_sel]].line); - if (!rb->kbd_input(buf,MAX_LINE_LEN)) + rb->strcpy(temp_line,&buffer[do_action(ACTION_GET,0,cur_sel)]); + if (!rb->kbd_input(temp_line,MAX_LINE_LEN)) { if (line_count) - rb->strcpy(lines[indicies[cur_sel]].line,buf); - else { add_line(buf, first); setup_lists(&lists); } + { + do_action(ACTION_UPDATE,temp_line,cur_sel); + } + else do_action(ACTION_INSERT,temp_line,cur_sel); changed = true; } } @@ -353,10 +414,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) break; #endif if (!line_count) break; - rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line); - del_line(indicies[cur_sel]); + rb->strcpy(copy_buffer,&buffer[do_action(ACTION_GET,0,cur_sel)]); + do_action(ACTION_REMOVE,0,cur_sel); changed = true; - setup_lists(&lists); break; #endif #ifdef TEXT_EDITOR_ITEM_MENU @@ -381,7 +441,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) break; case MENU_RET_UPDATE: changed = true; - setup_lists(&lists); break; case MENU_RET_NO_UPDATE: break; @@ -441,7 +500,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) break; } last_button = button; + rb->gui_synclist_set_nb_items(&lists,line_count); } - + rb->global_settings->statusbar = prev_show_statusbar; return PLUGIN_OK; }