1
0
Fork 0
forked from len0rd/rockbox

Patch #5374 - Updated text editor plugin from Jonathan Gordon.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9963 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dave Chapman 2006-05-20 10:16:03 +00:00
parent fa5caa0b5b
commit 4c3ada4428

View file

@ -50,121 +50,156 @@
#define TEXT_EDITOR_CANCEL BUTTON_POWER #define TEXT_EDITOR_CANCEL BUTTON_POWER
#define TEXT_EDITOR_ITEM_MENU BUTTON_PLAY #define TEXT_EDITOR_ITEM_MENU BUTTON_PLAY
#elif CONFIG_KEYPAD == GIGABEAT_PAD
#else #else
#error TEXT_EDITOR: Unsupported keypad #error TEXT_EDITOR: Unsupported keypad
#endif #endif
#define MAX_LINE_LEN 128
#if PLUGIN_BUFFER_SIZE > 0x45000 #if PLUGIN_BUFFER_SIZE > 0x45000
#define MAX_LINES 2048 #define MAX_CHARS 0x40000 /* 128 kiB */
#else #else
#define MAX_LINES 128 #define MAX_CHARS 0x6000 /* 24 kiB */
#endif #endif
#define MAX_LINE_LEN 2048
PLUGIN_HEADER PLUGIN_HEADER
static struct plugin_api* rb; static struct plugin_api* rb;
struct LineStruct { static char buffer[MAX_CHARS];
char line[MAX_LINE_LEN]; static char eol[3];
int prev; /* index to prev item, or -1 */ static int char_count = 0;
int next; /* index to next item, or -1 */ static int line_count = 0;
}; static int last_action_line = 0;
static int last_char_index = 0;
struct LineStruct lines[MAX_LINES]; #define ACTION_INSERT 0
int line_count = 0; #define ACTION_GET 1
int first = -1, last = -1; #define ACTION_REMOVE 2
int indicies[MAX_LINES]; #define ACTION_UPDATE 3
/**************************** stuff for the linked lists ***************/ #define ACTION_CONCAT 4
int build_indicies(void)
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; int r;
struct LineStruct *line; rb->cpu_boost(1);
if (first==-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;
}
while (i<line && i<line_count)
{
c += rb->strlen(&buffer[c])+1;
i++;
}
switch (action)
{
case ACTION_INSERT:
len = rb->strlen(str)+1;
if ( char_count+ len > MAX_CHARS )
return 0; return 0;
while (i<line_count) rb->memmove(&buffer[c+len],&buffer[c],char_count);
{ rb->strcpy(&buffer[c],str);
indicies[i++] = index; char_count += len;
DEBUGF("%d,",index);
line = &lines[index];
index = line->next;
}
DEBUGF("\n");
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++; line_count++;
return 1; 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;
temp = &lines[idx_after_me]; last_char_index = c;
next = lines[idx_after_me].next; return 1;
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 *list_get_name_cb(int selected_item,void* data,char* buf)
{ {
char *b = &buffer[do_action(ACTION_GET,0,selected_item)];
(void)data; (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; 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) void save_changes(int overwrite)
{ {
int fd; int fd;
@ -173,34 +208,37 @@ void save_changes(int overwrite)
if (!filename[0] || !overwrite) if (!filename[0] || !overwrite)
{ {
rb->strcpy(filename,"/"); rb->strcpy(filename,"/");
rb->kbd_input(filename,1024); rb->kbd_input(filename,MAX_PATH);
} }
fd = rb->open(filename,O_WRONLY|O_CREAT); fd = rb->open(filename,O_WRONLY|O_CREAT);
if (!fd) if (fd < 0)
{ {
rb->splash(HZ*2,1,"Changes NOT saved"); rb->splash(HZ*2,1,"Changes NOT saved");
return; return;
} }
rb->lcd_clear_display(); rb->lcd_clear_display();
build_indicies(); #ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(1);
#endif
for (i=0;i<line_count;i++) for (i=0;i<line_count;i++)
{ {
rb->fdprintf(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); 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_init(lists,list_get_name_cb,0);
rb->gui_synclist_set_icon_callback(lists,NULL); rb->gui_synclist_set_icon_callback(lists,NULL);
rb->gui_synclist_set_nb_items(lists,line_count); rb->gui_synclist_set_nb_items(lists,line_count);
rb->gui_synclist_limit_scroll(lists,true); 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); rb->gui_synclist_draw(lists);
} }
enum { enum {
@ -219,7 +257,6 @@ int do_item_menu(int cur_sel, char* copy_buffer)
{ "Insert Below", NULL }, { "Insert Below", NULL },
{ "", NULL }, { "", NULL },
{ "Cat To Above",NULL }, { "Cat To Above",NULL },
/* { "Split Line",NULL }, */
{ "", NULL }, { "", NULL },
{ "Save", NULL }, { "Save", NULL },
}; };
@ -229,12 +266,12 @@ int do_item_menu(int cur_sel, char* copy_buffer)
switch (rb->menu_show(m)) switch (rb->menu_show(m))
{ {
case 0: /* cut */ case 0: /* cut */
rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line); rb->strcpy(copy_buffer,&buffer[do_action(ACTION_GET,0,cur_sel)]);
del_line(indicies[cur_sel]); do_action(ACTION_REMOVE,0,cur_sel);
ret = MENU_RET_UPDATE; ret = MENU_RET_UPDATE;
break; break;
case 1: /* copy */ 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; ret = MENU_RET_NO_UPDATE;
break; break;
case 2: /* blank */ case 2: /* blank */
@ -244,7 +281,7 @@ int do_item_menu(int cur_sel, char* copy_buffer)
case 3: /* insert above */ case 3: /* insert above */
if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN)) 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'; copy_buffer[0]='\0';
ret = MENU_RET_UPDATE; ret = MENU_RET_UPDATE;
} }
@ -252,7 +289,7 @@ int do_item_menu(int cur_sel, char* copy_buffer)
case 4: /* insert below */ case 4: /* insert below */
if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN)) 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'; copy_buffer[0]='\0';
ret = MENU_RET_UPDATE; ret = MENU_RET_UPDATE;
} }
@ -263,13 +300,10 @@ int do_item_menu(int cur_sel, char* copy_buffer)
case 6: /* cat to above */ case 6: /* cat to above */
if (cur_sel>0) if (cur_sel>0)
{ {
rb->strcat(lines[indicies[cur_sel-1]].line,lines[indicies[cur_sel]].line); do_action(ACTION_CONCAT,0,cur_sel);
del_line(indicies[cur_sel]);
ret = MENU_RET_UPDATE; ret = MENU_RET_UPDATE;
} }
break; break;
/* case 7: // split line */
case 7: /* save */ case 7: /* save */
ret = MENU_RET_SAVE; ret = MENU_RET_SAVE;
break; 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) enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{ {
int fd; int fd;
char temp_line[MAX_LINE_LEN]; static char temp_line[MAX_LINE_LEN];
struct gui_synclist lists; struct gui_synclist lists;
bool exit = false; bool exit = false;
int button, last_button = BUTTON_NONE; int button, last_button = BUTTON_NONE;
bool changed = false; bool changed = false;
int cur_sel; int cur_sel=0;
char copy_buffer[MAX_LINE_LEN]; copy_buffer[0]='\0'; static char copy_buffer[MAX_LINE_LEN];
bool prev_show_statusbar;
rb = api; 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) if (parameter)
{ {
rb->strcpy(filename,(char*)parameter); rb->strcpy(filename,(char*)parameter);
if (!get_eol_string(filename))
{
rb->strcpy(eol,"\n");
}
fd = rb->open(filename,O_RDONLY); fd = rb->open(filename,O_RDONLY);
if (fd<0) if (fd<0)
{ {
@ -306,7 +353,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
/* read in the file */ /* read in the file */
while (rb->read_line(fd,temp_line,MAX_LINE_LEN)) 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->splash(HZ*2,true,"Error reading file: %s",(char*)parameter);
rb->close(fd); rb->close(fd);
@ -315,16 +362,30 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
} }
rb->close(fd); 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 */ /* now dump it in the list */
setup_lists(&lists); setup_lists(&lists,0);
rb->lcd_update();
while (!exit) while (!exit)
{ {
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(1);
#endif
rb->gui_synclist_draw(&lists); rb->gui_synclist_draw(&lists);
cur_sel = rb->gui_synclist_get_sel_pos(&lists); cur_sel = rb->gui_synclist_get_sel_pos(&lists);
button = rb->button_get(true); button = rb->button_get(true);
if (rb->gui_synclist_do_button(&lists,button)) if (rb->gui_synclist_do_button(&lists,button))
continue; continue;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(0);
#endif
switch (button) switch (button)
{ {
case TEXT_EDITOR_SELECT: 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) if (last_button != TEXT_EDITOR_SELECT_PRE)
break; break;
#endif #endif
char buf[MAX_LINE_LEN];buf[0]='\0';
if (line_count) if (line_count)
rb->strcpy(buf,lines[indicies[cur_sel]].line); rb->strcpy(temp_line,&buffer[do_action(ACTION_GET,0,cur_sel)]);
if (!rb->kbd_input(buf,MAX_LINE_LEN)) if (!rb->kbd_input(temp_line,MAX_LINE_LEN))
{ {
if (line_count) 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; changed = true;
} }
} }
@ -353,10 +414,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
break; break;
#endif #endif
if (!line_count) break; if (!line_count) break;
rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line); rb->strcpy(copy_buffer,&buffer[do_action(ACTION_GET,0,cur_sel)]);
del_line(indicies[cur_sel]); do_action(ACTION_REMOVE,0,cur_sel);
changed = true; changed = true;
setup_lists(&lists);
break; break;
#endif #endif
#ifdef TEXT_EDITOR_ITEM_MENU #ifdef TEXT_EDITOR_ITEM_MENU
@ -381,7 +441,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
break; break;
case MENU_RET_UPDATE: case MENU_RET_UPDATE:
changed = true; changed = true;
setup_lists(&lists);
break; break;
case MENU_RET_NO_UPDATE: case MENU_RET_NO_UPDATE:
break; break;
@ -441,7 +500,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
break; break;
} }
last_button = button; last_button = button;
rb->gui_synclist_set_nb_items(&lists,line_count);
} }
rb->global_settings->statusbar = prev_show_statusbar;
return PLUGIN_OK; return PLUGIN_OK;
} }