summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorHristo Kovachev <bger@rockbox.org>2006-04-03 08:51:08 +0000
committerHristo Kovachev <bger@rockbox.org>2006-04-03 08:51:08 +0000
commit38deb8f13a9896f2d6eb884c6a8bbc9b10001255 (patch)
tree6e0b2629bec1f6ebd83671230652da304dcf0ff8 /apps
parentdefbc69b2b2a576d06e718deef73aa41b5376390 (diff)
downloadrockbox-38deb8f13a9896f2d6eb884c6a8bbc9b10001255.tar.gz
rockbox-38deb8f13a9896f2d6eb884c6a8bbc9b10001255.zip
Patch #4864 by Jonathan Gordon: text editor plugin, with some changes by me.
Also correct a var clash between the rockbox's gui api and doom plugin git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9451 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/gui/list.c8
-rw-r--r--apps/gui/list.h6
-rw-r--r--apps/plugin.c22
-rw-r--r--apps/plugin.h29
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/doom/f_wipe.c10
-rw-r--r--apps/plugins/doom/i_video.c16
-rw-r--r--apps/plugins/doom/r_draw.c4
-rw-r--r--apps/plugins/doom/st_stuff.c4
-rw-r--r--apps/plugins/doom/v_video.c32
-rw-r--r--apps/plugins/doom/v_video.h8
-rw-r--r--apps/plugins/text_editor.c447
-rw-r--r--apps/plugins/viewers.config4
13 files changed, 549 insertions, 42 deletions
diff --git a/apps/gui/list.c b/apps/gui/list.c
index 8ca3042a4b..d0117d7c03 100644
--- a/apps/gui/list.c
+++ b/apps/gui/list.c
@@ -491,6 +491,14 @@ void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items)
#endif
}
}
+int gui_synclist_get_nb_items(struct gui_synclist * lists)
+{
+ return gui_list_get_nb_items(&((lists)->gui_list[0]));
+}
+int gui_synclist_get_sel_pos(struct gui_synclist * lists)
+{
+ return gui_list_get_sel_pos(&((lists)->gui_list[0]));
+}
void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback)
{
int i;
diff --git a/apps/gui/list.h b/apps/gui/list.h
index e72e00c5d1..48b7a5e0fc 100644
--- a/apps/gui/list.h
+++ b/apps/gui/list.h
@@ -337,14 +337,10 @@ extern void gui_synclist_init(
);
extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items);
extern void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback);
-#define gui_synclist_get_nb_items(lists) \
- gui_list_get_nb_items(&((lists)->gui_list[0]))
+extern int gui_synclist_get_nb_items(struct gui_synclist * lists);
extern int gui_synclist_get_sel_pos(struct gui_synclist * lists);
-#define gui_synclist_get_sel_pos(lists) \
- gui_list_get_sel_pos(&((lists)->gui_list[0]))
-
extern void gui_synclist_draw(struct gui_synclist * lists);
extern void gui_synclist_select_item(struct gui_synclist * lists,
int item_number);
diff --git a/apps/plugin.c b/apps/plugin.c
index 6cbda49a48..57bc09530a 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -52,6 +52,7 @@
#include "sound.h"
#include "database.h"
#include "splash.h"
+#include "list.h"
#if (CONFIG_CODEC == SWCODEC)
#include "pcm_playback.h"
#include "dsp.h"
@@ -412,6 +413,27 @@ static const struct plugin_api rockbox_api = {
vsnprintf,
memchr,
+ /* list */
+ gui_synclist_init,
+ gui_synclist_set_nb_items,
+ gui_synclist_set_icon_callback,
+ gui_synclist_get_nb_items,
+ gui_synclist_get_sel_pos,
+ gui_synclist_draw,
+ gui_synclist_select_item,
+ gui_synclist_select_next,
+ gui_synclist_select_previous,
+ gui_synclist_select_next_page,
+ gui_synclist_select_previous_page,
+ gui_synclist_add_item,
+ gui_synclist_del_item,
+ gui_synclist_limit_scroll,
+ gui_synclist_flash,
+#ifdef HAVE_LCD_BITMAP
+ gui_synclist_scroll_right,
+ gui_synclist_scroll_left,
+#endif
+ gui_synclist_do_button,
};
int plugin_load(const char* plugin, void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index 4061346eba..d39e92de9c 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -67,6 +67,7 @@
#include "sound.h"
#include "menu.h"
#include "rbunicode.h"
+#include "list.h"
#ifdef HAVE_REMOTE_LCD
#include "lcd-remote.h"
@@ -102,7 +103,7 @@
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 17
+#define PLUGIN_API_VERSION 18
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
@@ -483,6 +484,32 @@ struct plugin_api {
int (*vsnprintf)(char *buf, int size, const char *fmt, va_list ap);
void *(*memchr)(const void *s1, int c, size_t n);
+
+ /* list */
+ void (*gui_synclist_init)(struct gui_synclist * lists,
+ list_get_name callback_get_item_name,void * data);
+ void (*gui_synclist_set_nb_items)(struct gui_synclist * lists, int nb_items);
+ void (*gui_synclist_set_icon_callback)(struct gui_synclist * lists, list_get_icon icon_callback);
+ int (*gui_synclist_get_nb_items)(struct gui_synclist * lists);
+ int (*gui_synclist_get_sel_pos)(struct gui_synclist * lists);
+ void (*gui_synclist_draw)(struct gui_synclist * lists);
+ void (*gui_synclist_select_item)(struct gui_synclist * lists,
+ int item_number);
+ void (*gui_synclist_select_next)(struct gui_synclist * lists);
+ void (*gui_synclist_select_previous)(struct gui_synclist * lists);
+ void (*gui_synclist_select_next_page)(struct gui_synclist * lists,
+ enum screen_type screen);
+ void (*gui_synclist_select_previous_page)(struct gui_synclist * lists,
+ enum screen_type screen);
+ void (*gui_synclist_add_item)(struct gui_synclist * lists);
+ void (*gui_synclist_del_item)(struct gui_synclist * lists);
+ void (*gui_synclist_limit_scroll)(struct gui_synclist * lists, bool scroll);
+ void (*gui_synclist_flash)(struct gui_synclist * lists);
+#ifdef HAVE_LCD_BITMAP
+ void (*gui_synclist_scroll_right)(struct gui_synclist * lists);
+ void (*gui_synclist_scroll_left)(struct gui_synclist * lists);
+#endif
+ unsigned (*gui_synclist_do_button)(struct gui_synclist * lists, unsigned button);
};
/* plugin header */
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index b777791f69..029b622fdf 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -26,6 +26,7 @@ wavplay.c
#ifndef IRIVER_IFP7XX_SERIES /* Temporarily disable plugins for iFP7xx */
dice.c
#ifdef HAVE_LCD_BITMAP /* Not for the Player */
+text_editor.c
#if CONFIG_LCD != LCD_IPOD2BPP /* Plugins needing the grayscale lib */
fire.c
diff --git a/apps/plugins/doom/f_wipe.c b/apps/plugins/doom/f_wipe.c
index a6251f295e..f51224f5ce 100644
--- a/apps/plugins/doom/f_wipe.c
+++ b/apps/plugins/doom/f_wipe.c
@@ -140,7 +140,7 @@ static int wipe_doMelt(int width, int height, int ticks)
return done;
}
-// CPhipps - modified to allocate and deallocate screens[2 to 3] as needed, saving memory
+// CPhipps - modified to allocate and deallocate d_screens[2 to 3] as needed, saving memory
static int wipe_exitMelt(int width, int height, int ticks)
{
@@ -152,20 +152,20 @@ static int wipe_exitMelt(int width, int height, int ticks)
free(wipe_scr_end);
// Paranoia
y = NULL;
- wipe_scr_start = wipe_scr_end = screens[SRC_SCR] = screens[DEST_SCR] = NULL;
+ wipe_scr_start = wipe_scr_end = d_screens[SRC_SCR] = d_screens[DEST_SCR] = NULL;
return 0;
}
int wipe_StartScreen(int x, int y, int width, int height)
{
- wipe_scr_start = screens[SRC_SCR] = malloc(SCREENWIDTH * SCREENHEIGHT);
+ wipe_scr_start = d_screens[SRC_SCR] = malloc(SCREENWIDTH * SCREENHEIGHT);
V_CopyRect(x, y, 0, width, height, x, y, SRC_SCR, VPT_NONE ); // Copy start screen to buffer
return 0;
}
int wipe_EndScreen(int x, int y, int width, int height)
{
- wipe_scr_end = screens[DEST_SCR] = malloc(SCREENWIDTH * SCREENHEIGHT);
+ wipe_scr_end = d_screens[DEST_SCR] = malloc(SCREENWIDTH * SCREENHEIGHT);
V_CopyRect(x, y, 0, width, height, x, y, DEST_SCR, VPT_NONE); // Copy end screen to buffer
V_CopyRect(x, y, SRC_SCR, width, height, x, y, 0 , VPT_NONE); // restore start screen
return 0;
@@ -180,7 +180,7 @@ int wipe_ScreenWipe(int x, int y, int width, int height, int ticks)
if (!go) // initial stuff
{
go = 1;
- wipe_scr = screens[0];
+ wipe_scr = d_screens[0];
wipe_initMelt(width, height, ticks);
}
V_MarkRect(0, 0, width, height); // do a piece of wipe-in
diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c
index 6adb9491a4..ea6389deab 100644
--- a/apps/plugins/doom/i_video.c
+++ b/apps/plugins/doom/i_video.c
@@ -16,7 +16,11 @@
* GNU General Public License for more details.
*
* $Log$
- * Revision 1.4 2006/04/02 20:45:24 kkurbjun
+ * Revision 1.5 2006/04/03 08:51:08 bger
+ * Patch #4864 by Jonathan Gordon: text editor plugin, with some changes by me.
+ * Also correct a var clash between the rockbox's gui api and doom plugin
+ *
+ * Revision 1.4 2006-04-02 20:45:24 kkurbjun
* Properly ifdef H300 video code, fix commented line handling rockbox volume
*
* Revision 1.3 2006-04-02 01:52:44 kkurbjun
@@ -336,7 +340,7 @@ void I_FinishUpdate (void)
*(volatile unsigned short *) 0xf0000002 = 0; // value
*(volatile unsigned short *) 0xf0000000 = 0x22; // GRAM
- unsigned char *screenptr=screens[0];
+ unsigned char *screenptr=d_screens[0];
int wcnt=0, hcnt=0;
while(hcnt<LCD_HEIGHT)
@@ -358,7 +362,7 @@ void I_FinishUpdate (void)
{
for (x = 0; x < LCD_WIDTH; x++)
{
- paletteIndex = screens[0][y*SCREENWIDTH + x];
+ paletteIndex = d_screens[0][y*SCREENWIDTH + x];
rb->lcd_framebuffer[y * LCD_WIDTH + x] = palette[paletteIndex];
}
}
@@ -371,7 +375,7 @@ void I_FinishUpdate (void)
//
void I_ReadScreen (byte* scr)
{
- memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
+ memcpy (scr, d_screens[0], SCREENWIDTH*SCREENHEIGHT);
}
//
@@ -399,9 +403,9 @@ void I_InitGraphics(void)
#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
- screens[0] = fastscreen;
+ d_screens[0] = fastscreen;
#else
// Don't know if this will fit in other IRAMs
- screens[0] = malloc (SCREENWIDTH * SCREENHEIGHT * sizeof(unsigned char));
+ d_screens[0] = malloc (SCREENWIDTH * SCREENHEIGHT * sizeof(unsigned char));
#endif
}
diff --git a/apps/plugins/doom/r_draw.c b/apps/plugins/doom/r_draw.c
index b6d84f0dff..a6bc21e420 100644
--- a/apps/plugins/doom/r_draw.c
+++ b/apps/plugins/doom/r_draw.c
@@ -573,7 +573,7 @@ void R_InitBuffer(int width, int height)
viewwindowy = width==SCREENWIDTH ? 0 : (SCREENHEIGHT-(ST_SCALED_HEIGHT-1)-height)>>1;
- topleft = screens[0] + viewwindowy*SCREENWIDTH + viewwindowx;
+ topleft = d_screens[0] + viewwindowy*SCREENWIDTH + viewwindowx;
// Preclaculate all row offsets.
// CPhipps - merge viewwindowx into here
@@ -627,7 +627,7 @@ void R_FillBackScreen (void)
void R_VideoErase(unsigned ofs, int count)
{
- memcpy(screens[0]+ofs, screens[1]+ofs, count); // LFB copy.
+ memcpy(d_screens[0]+ofs, d_screens[1]+ofs, count); // LFB copy.
}
//
diff --git a/apps/plugins/doom/st_stuff.c b/apps/plugins/doom/st_stuff.c
index 5d9244d951..feae89a802 100644
--- a/apps/plugins/doom/st_stuff.c
+++ b/apps/plugins/doom/st_stuff.c
@@ -1148,6 +1148,6 @@ void ST_Init(void)
veryfirsttime = 0;
ST_loadData();
// proff 08/18/98: Changed for high-res
- screens[4] = Z_Malloc(SCREENWIDTH*(ST_SCALED_HEIGHT+1), PU_STATIC, 0);
- // screens[4] = Z_Malloc(ST_WIDTH*ST_HEIGHT, PU_STATIC, 0);
+ d_screens[4] = Z_Malloc(SCREENWIDTH*(ST_SCALED_HEIGHT+1), PU_STATIC, 0);
+ // d_screens[4] = Z_Malloc(ST_WIDTH*ST_HEIGHT, PU_STATIC, 0);
}
diff --git a/apps/plugins/doom/v_video.c b/apps/plugins/doom/v_video.c
index 75ccc3ffda..ca90c4b293 100644
--- a/apps/plugins/doom/v_video.c
+++ b/apps/plugins/doom/v_video.c
@@ -44,7 +44,7 @@
#include "m_swap.h"
#include "rockmacros.h"
// Each screen is [SCREENWIDTH*SCREENHEIGHT];
-byte *screens[6] IBSS_ATTR;
+byte *d_screens[6] IBSS_ATTR;
int dirtybox[4];
/* jff 4/24/98 initialize this at runtime */
@@ -239,8 +239,8 @@ void V_CopyRect(int srcx, int srcy, int srcscrn, int width,
V_MarkRect (destx, desty, width, height);
- src = screens[srcscrn]+SCREENWIDTH*srcy+srcx;
- dest = screens[destscrn]+SCREENWIDTH*desty+destx;
+ src = d_screens[srcscrn]+SCREENWIDTH*srcy+srcx;
+ dest = d_screens[destscrn]+SCREENWIDTH*desty+destx;
for ( ; height>0 ; height--)
{
@@ -294,7 +294,7 @@ void V_DrawBlock(int x, int y, int scrn, int width, int height,
if (!scrn)
V_MarkRect (x, y, width, height);
- dest = screens[scrn] + y*SCREENWIDTH+x;
+ dest = d_screens[scrn] + y*SCREENWIDTH+x;
// x & y no longer needed
while (height--) {
@@ -308,7 +308,7 @@ void V_DrawBlock(int x, int y, int scrn, int width, int height,
} else {
V_MarkRect (x, y, width, height);
- dest = screens[scrn] + y*SCREENWIDTH+x;
+ dest = d_screens[scrn] + y*SCREENWIDTH+x;
while (height--) {
memcpy (dest, src, width);
@@ -369,7 +369,7 @@ void V_GetBlock(int x, int y, int scrn, int width, int height, byte *dest)
I_Error ("V_GetBlock: Bad arguments");
#endif
- src = screens[scrn] + y*SCREENWIDTH+x;
+ src = d_screens[scrn] + y*SCREENWIDTH+x;
while (height--)
{
@@ -394,13 +394,13 @@ void V_Init (void)
#define PREALLOCED_SCREENS 2
// CPhipps - no point in "stick these in low dos memory on PCs" anymore
- // Allocate the screens individually, so I_InitGraphics can release screens[0]
+ // Allocate the screens individually, so I_InitGraphics can release d_screens[0]
// if e.g. it wants a MitSHM buffer instead
for (i=0 ; i<PREALLOCED_SCREENS ; i++)
- screens[i] = calloc(SCREENWIDTH*SCREENHEIGHT, 1);
+ d_screens[i] = calloc(SCREENWIDTH*SCREENHEIGHT, 1);
for (; i<4; i++) // Clear the rest (paranoia)
- screens[i] = NULL;
+ d_screens[i] = NULL;
}
//
@@ -448,7 +448,7 @@ void V_DrawMemPatch(int x, int y, int scrn, const patch_t *patch,
if (!(flags & VPT_STRETCH)) {
unsigned int col;
const column_t *column;
- byte *desttop = screens[scrn]+y*SCREENWIDTH+x;
+ byte *desttop = d_screens[scrn]+y*SCREENWIDTH+x;
unsigned int w = SHORT(patch->width);
if (!scrn)
@@ -544,7 +544,7 @@ void V_DrawMemPatch(int x, int y, int scrn, const patch_t *patch,
V_MarkRect ( stretchx, stretchy, (SHORT( patch->width ) * DX ) >> 16,
(SHORT( patch->height) * DY ) >> 16 );
- desttop = screens[scrn] + stretchy * SCREENWIDTH + stretchx;
+ desttop = d_screens[scrn] + stretchy * SCREENWIDTH + stretchx;
for ( col = 0; col <= w; x++, col+=DXI, desttop++ ) {
const column_t *column;
@@ -640,11 +640,11 @@ byte *V_PatchToBlock(const char* name, int cm,
enum patch_translation_e flags,
unsigned short* width, unsigned short* height)
{
- byte *oldscr = screens[1];
+ byte *oldscr = d_screens[1];
byte *block;
const patch_t *patch;
- screens[1] = calloc(SCREENWIDTH*SCREENHEIGHT, 1);
+ d_screens[1] = calloc(SCREENWIDTH*SCREENHEIGHT, 1);
patch = W_CacheLumpName(name);
V_DrawMemPatch(SHORT(patch->leftoffset), SHORT(patch->topoffset),
@@ -662,8 +662,8 @@ byte *V_PatchToBlock(const char* name, int cm,
V_GetBlock(0, 0, 1, *width, *height,
block = malloc((long)(*width) * (*height)));
- free(screens[1]);
- screens[1] = oldscr;
+ free(d_screens[1]);
+ d_screens[1] = oldscr;
return block;
}
#endif /* GL_DOOM */
@@ -691,7 +691,7 @@ void V_SetPalette(int pal)
#ifndef GL_DOOM
void V_FillRect(int scrn, int x, int y, int width, int height, byte colour)
{
- byte* dest = screens[scrn] + x + y*SCREENWIDTH;
+ byte* dest = d_screens[scrn] + x + y*SCREENWIDTH;
while (height--) {
memset(dest, colour, width);
dest += SCREENWIDTH;
diff --git a/apps/plugins/doom/v_video.h b/apps/plugins/doom/v_video.h
index c9926e8997..c4b8927109 100644
--- a/apps/plugins/doom/v_video.h
+++ b/apps/plugins/doom/v_video.h
@@ -72,7 +72,7 @@ typedef enum
#define CR_DEFAULT CR_RED /* default value for out of range colors */
-extern byte *screens[6];
+extern byte *d_screens[6];
extern int dirtybox[4];
extern const byte gammatable[5][256];
extern int usegamma;
@@ -173,11 +173,11 @@ void V_SetPalette(int pal);
// CPhipps - function to plot a pixel
#ifndef GL_DOOM
-#define V_PlotPixel(s,x,y,c) screens[s][x+SCREENWIDTH*y]=c
+#define V_PlotPixel(s,x,y,c) d_screens[s][x+SCREENWIDTH*y]=c
#endif
-#define V_AllocScreen(scrn) screens[scrn] = malloc(SCREENWIDTH*SCREENHEIGHT)
-#define V_FreeScreen(scrn) free(screens[scrn]); screens[scrn] = NULL
+#define V_AllocScreen(scrn) d_screens[scrn] = malloc(SCREENWIDTH*SCREENHEIGHT)
+#define V_FreeScreen(scrn) free(d_screens[scrn]); d_screens[scrn] = NULL
#ifdef GL_DOOM
#include "gl_struct.h"
diff --git a/apps/plugins/text_editor.c b/apps/plugins/text_editor.c
new file mode 100644
index 0000000000..6767940938
--- /dev/null
+++ b/apps/plugins/text_editor.c
@@ -0,0 +1,447 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Jonathan Gordon
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+/* button definitions, every keypad must only have select,menu and cancel */
+#if CONFIG_KEYPAD == RECORDER_PAD
+#define TEXT_EDITOR_SELECT BUTTON_PLAY
+#define TEXT_EDITOR_CANCEL BUTTON_OFF
+#define TEXT_EDITOR_ITEM_MENU BUTTON_F1
+
+#elif CONFIG_KEYPAD == ONDIO_PAD
+#define TEXT_EDITOR_SELECT_PRE BUTTON_MENU
+#define TEXT_EDITOR_SELECT (BUTTON_MENU|BUTTON_REL)
+#define TEXT_EDITOR_CANCEL BUTTON_OFF
+#define TEXT_EDITOR_ITEM_MENU BUTTON_MENU|BUTTON_REPEAT
+
+#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
+#define TEXT_EDITOR_SELECT BUTTON_SELECT
+#define TEXT_EDITOR_CANCEL BUTTON_OFF
+#define TEXT_EDITOR_DELETE BUTTON_REC
+#define TEXT_EDITOR_ITEM_MENU BUTTON_MODE
+
+#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define TEXT_EDITOR_SELECT_PRE BUTTON_SELECT
+#define TEXT_EDITOR_SELECT ( BUTTON_SELECT | BUTTON_REL)
+#define TEXT_EDITOR_CANCEL_PRE BUTTON_SELECT
+#define TEXT_EDITOR_CANCEL (BUTTON_SELECT | BUTTON_MENU)
+#define TEXT_EDITOR_DELETE (BUTTON_LEFT)
+#define TEXT_EDITOR_ITEM_MENU (BUTTON_MENU)
+
+#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
+
+#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
+#define TEXT_EDITOR_SELECT BUTTON_SELECT
+#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
+#else
+#define MAX_LINES 128
+#endif
+
+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 */
+};
+
+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 i=0, index = first;
+ struct LineStruct *line;
+ if (first==-1)
+ return 0;
+ while (i<line_count)
+ {
+ indicies[i++] = index;
+ 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++;
+ 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)
+{
+ (void)data;
+ rb->strcpy(buf,lines[indicies[selected_item]].line);
+ return buf;
+}
+char filename[1024];
+void save_changes(int overwrite)
+{
+ int fd;
+ int i;
+
+ if (!filename[0] || overwrite)
+ {
+ rb->strcpy(filename,"/");
+ rb->kbd_input(filename,1024);
+ }
+
+ fd = rb->open(filename,O_WRONLY|O_CREAT);
+ if (!fd)
+ {
+ rb->splash(HZ*2,1,"Changes NOT saved");
+ return;
+ }
+
+ rb->lcd_clear_display();
+ build_indicies();
+ for (i=0;i<line_count;i++)
+ {
+ rb->fdprintf(fd,"%s\n",lines[indicies[i]].line);
+ }
+
+ rb->close(fd);
+}
+
+void setup_lists(struct gui_synclist *lists)
+{
+ 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_draw(lists);
+}
+enum {
+ MENU_RET_SAVE = -1,
+ MENU_RET_NO_UPDATE,
+ MENU_RET_UPDATE,
+};
+int do_item_menu(int cur_sel, char* copy_buffer)
+{
+ int m, ret = 0;
+ static const struct menu_item items[] = {
+ { "Cut", NULL },
+ { "Copy", NULL },
+ { "", NULL },
+ { "Insert Above", NULL },
+ { "Insert Below", NULL },
+ { "", NULL },
+ { "Cat To Above",NULL },
+ /* { "Split Line",NULL }, */
+ { "", NULL },
+ { "Save", NULL },
+ };
+ m = rb->menu_init(items, sizeof(items) / sizeof(*items),
+ NULL, NULL, NULL, NULL);
+
+ switch (rb->menu_show(m))
+ {
+ case 0: /* cut */
+ rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line);
+ del_line(indicies[cur_sel]);
+ ret = MENU_RET_UPDATE;
+ break;
+ case 1: /* copy */
+ rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line);
+ ret = MENU_RET_NO_UPDATE;
+ break;
+ case 2: /* blank */
+ ret = MENU_RET_NO_UPDATE;
+ break;
+
+ case 3: /* insert above */
+ if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN))
+ {
+ add_line(copy_buffer,lines[indicies[cur_sel]].prev);
+ copy_buffer[0]='\0';
+ ret = MENU_RET_UPDATE;
+ }
+ break;
+ case 4: /* insert below */
+ if (!rb->kbd_input(copy_buffer,MAX_LINE_LEN))
+ {
+ add_line(copy_buffer,indicies[cur_sel]);
+ copy_buffer[0]='\0';
+ ret = MENU_RET_UPDATE;
+ }
+ break;
+ case 5: /* blank */
+ ret = MENU_RET_NO_UPDATE;
+ break;
+ 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]);
+ ret = MENU_RET_UPDATE;
+ }
+ break;
+ /* case 7: // split line */
+
+ case 7: /* save */
+ ret = MENU_RET_SAVE;
+ break;
+ default:
+ ret = MENU_RET_NO_UPDATE;
+ break;
+ }
+ rb->menu_exit(m);
+ return ret;
+}
+/* this is the plugin entry point */
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+ int fd;
+ 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';
+
+ rb = api;
+ if (parameter)
+ {
+ rb->strcpy(filename,(char*)parameter);
+ fd = rb->open(filename,O_RDONLY);
+ if (fd<0)
+ {
+ rb->splash(HZ*2,true,"Couldnt open file: %s",(char*)parameter);
+ return PLUGIN_ERROR;
+ }
+ /* read in the file */
+ while (rb->read_line(fd,temp_line,MAX_LINE_LEN))
+ {
+ if (add_line(temp_line,last) < 0)
+ {
+ rb->splash(HZ*2,true,"Error reading file: %s",(char*)parameter);
+ rb->close(fd);
+ return PLUGIN_ERROR;
+ }
+ }
+ rb->close(fd);
+ }
+ else filename[0] = '\0';
+ /* now dump it in the list */
+ setup_lists(&lists);
+ while (!exit)
+ {
+ 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;
+ switch (button)
+ {
+ case TEXT_EDITOR_SELECT:
+ {
+#ifdef TEXT_EDITOR_SELECT_PRE
+ 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))
+ {
+ if (line_count)
+ rb->strcpy(lines[indicies[cur_sel]].line,buf);
+ else { add_line(buf, first); setup_lists(&lists); }
+ changed = true;
+ }
+ }
+ break;
+#ifdef TEXT_EDITOR_DELETE
+ case TEXT_EDITOR_DELETE:
+#ifdef TEXT_EDITOR_DELETE_PRE
+ if (last_button != TEXT_EDITOR_DELETE_PRE)
+ break;
+#endif
+ if (!line_count) break;
+ rb->strcpy(copy_buffer,lines[indicies[cur_sel]].line);
+ del_line(indicies[cur_sel]);
+ changed = true;
+ setup_lists(&lists);
+ break;
+#endif
+#ifdef TEXT_EDITOR_ITEM_MENU
+ case TEXT_EDITOR_ITEM_MENU:
+#ifdef TEXT_EDITOR_RC_ITEM_MENU
+ case TEXT_EDITOR_RC_ITEM_MENU:
+#endif
+#ifdef TEXT_EDITOR_ITEM_MENU_PRE
+ if (lastbutton != TEXT_EDITOR_ITEM_MENU_PRE
+#ifdef TEXT_EDITOR_RC_ITEM_MENU_PRE
+ && lastbutton != TEXT_EDITOR_RC_ITEM_MENU_PRE
+#endif
+ )
+ break;
+#endif
+ { /* do the item menu */
+ switch (do_item_menu(cur_sel, copy_buffer))
+ {
+ case MENU_RET_SAVE:
+ save_changes(1);
+ changed = false;
+ break;
+ case MENU_RET_UPDATE:
+ changed = true;
+ setup_lists(&lists);
+ break;
+ case MENU_RET_NO_UPDATE:
+ break;
+ }
+ }
+ break;
+#endif /* TEXT_EDITOR_ITEM_MENU */
+ case TEXT_EDITOR_CANCEL:
+#ifdef TEXT_EDITOR_CANCEL_PRE
+ if (last_button != TEXT_EDITOR_CANCEL_PRE)
+ break;
+#endif
+ if (changed)
+ {
+ int m;
+ int result;
+
+ static const struct menu_item items[] = {
+ { "Return", NULL },
+ { " ", NULL },
+ { "Save Changes", NULL },
+ { "Save As...", NULL },
+ { " ", NULL },
+ { "Save and Exit", NULL },
+ { "Ignore Changes and Exit", NULL },
+ };
+
+ m = rb->menu_init(items, sizeof(items) / sizeof(*items),
+ NULL, NULL, NULL, NULL);
+
+ result=rb->menu_show(m);
+
+ switch (result)
+ {
+ case 0:
+ break;
+ case 2: //save to disk
+ save_changes(1);
+ changed = 0;
+ break;
+ case 3:
+ save_changes(0);
+ changed = 0;
+ break;
+
+ case 5:
+ save_changes(1);
+ exit=1;
+ break;
+ case 6:
+ exit=1;
+ break;
+ }
+ rb->menu_exit(m);
+ }
+ else exit=1;
+ break;
+ }
+ last_button = button;
+ }
+
+ return PLUGIN_OK;
+}
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index a4dcc3695b..6de2bd883a 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -1,6 +1,7 @@
ch8,viewers/chip8,70 70 7f 7f 70 70
txt,viewers/viewer,55 55 55 55 55 55
nfo,viewers/viewer,55 55 55 55 55 55
+txt,rocks/text_editor, 55 55 55 55 55 55
jpg,viewers/jpeg,18 24 3C 3C 24 18
ucl,viewers/rockbox_flash,2A 7F 41 41 7F 2A
rvf,viewers/video,5D 7F 5D 7F 5D 7F
@@ -15,4 +16,5 @@ rsp,viewers/searchengine, 0e 11 11 31 7e 60
ss,rocks/sudoku, 55 55 55 55 55 55
wav,viewers/wav2wv, 00 00 00 00 00 00
wav,viewers/mp3_encoder, 00 00 00 00 00 00
-wav,viewers/wavplay,60 7F 05 35 3F 00 \ No newline at end of file
+wav,viewers/wavplay,60 7F 05 35 3F 00
+