summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-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 @@
#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;
+
+#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 r;
+ rb->cpu_boost(1);
+ r = _do_action(action,str,line);
+ rb->cpu_boost(0);
+ return r;
+}
+#endif
-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)
+int _do_action(int action, char* str, int line)
{
- int i=0, index = first;
- struct LineStruct *line;
- if (first==-1)
- return 0;
- while (i<line_count)
+ int len;
+ int i=0,c=0;
+ if (line>=last_action_line)
{
- indicies[i++] = index;
- DEBUGF("%d,",index);
- line = &lines[index];
- index = line->next;
-
+ 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;
+ 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;
}
- DEBUGF("\n");
+ last_action_line = i;
+ last_char_index = c;
return 1;
}
-
-int find_first_free(int start)
+char *list_get_name_cb(int selected_item,void* data,char* buf)
{
- int i;
- if ((start <0) || (start >=MAX_LINES))
- start = 0;
- i = start;
- do
+ char *b = &buffer[do_action(ACTION_GET,0,selected_item)];
+ (void)data;
+ if (rb->strlen(b) >= MAX_PATH)
{
- if (lines[i].line[0] == '\0')
- return i;
- i = (i+1)%MAX_LINES;
- } while (i!=start);
- return -1;
+ 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;
}
-
-int add_line(char *line, int idx_after_me)
+char filename[MAX_PATH];
+int get_eol_string(char* fn)
{
- 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 */
+ 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])
{
- 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;
+ 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");
+ }
}
-
- 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;
+ rb->close(fd);
+ return 1;
}
-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)
-{
- (void)data;
- rb->strcpy(buf,lines[indicies[selected_item]].line);
- return buf;
-}
-char filename[1024];
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;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);
}
-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;
}