aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Bodenmann <joel@unormal.org>2013-12-18 16:49:49 +0100
committerJoel Bodenmann <joel@unormal.org>2013-12-18 16:49:49 +0100
commitaa2f7585ce088c505ac955dcb4a9091a4eb22b63 (patch)
treeab95a056d4d135ae7de4e7c1dd21309177eb1dec
parent92750f02078b898a5f35957e68ba61a689dc2a85 (diff)
downloaduGFX-aa2f7585ce088c505ac955dcb4a9091a4eb22b63.tar.gz
uGFX-aa2f7585ce088c505ac955dcb4a9091a4eb22b63.tar.bz2
uGFX-aa2f7585ce088c505ac955dcb4a9091a4eb22b63.zip
first implementation of console buffer. This has to be tested first - might contain bugs
-rw-r--r--include/gwin/console.h23
-rw-r--r--include/gwin/options.h11
-rw-r--r--src/gwin/console.c121
-rw-r--r--src/gwin/gwin.c13
4 files changed, 147 insertions, 21 deletions
diff --git a/include/gwin/console.h b/include/gwin/console.h
index a2dde96b..850c5a57 100644
--- a/include/gwin/console.h
+++ b/include/gwin/console.h
@@ -31,6 +31,13 @@ typedef struct GConsoleObject {
GWindowObject g;
coord_t cx, cy; // Cursor position
+ #if GWIN_CONSOLE_NEED_HISTORY
+ char* buffer; // buffer to store console content
+ uint16_t last_char; // the last rendered character
+ size_t size; // size of buffer
+ bool_t store; // shall PutChar() store into buffer
+ #endif
+
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
struct GConsoleWindowStream_t {
const struct GConsoleWindowVMT_t *vmt;
@@ -82,6 +89,22 @@ GHandle gwinGConsoleCreate(GDisplay *g, GConsoleObject *gc, const GWindowInit *p
BaseSequentialStream *gwinConsoleGetStream(GHandle gh);
#endif
+#if GWIN_CONSOLE_NEED_HISTORY
+ /**
+ * @brief Assing a buffer to keep track of the content while the widget is invisible.
+ * @pre GWIN_CONSOLE_NEED_HISTORY must be set to TRUE in your gfxconf.h
+ *
+ * @param[in] gh The window handle (must be a console window)
+ * @param[in] buffer The pointer of the buffer that shall be used. Buffer will be
+ * dynamically allocated when this is NULL.
+ * @param[in] size Size of the buffer that has been passed. If buffer is NULL, this
+ * will be the size of the dynamically allocated buffer.
+ *
+ * @return TRUE on success
+ */
+ bool_t gwinConsoleSetBuffer(GHandle gh, void* buffer, size_t size);
+#endif
+
/**
* @brief Put a character at the cursor position in the window.
* @note Uses the current foreground color to draw the character and fills the background using the background drawing color
diff --git a/include/gwin/options.h b/include/gwin/options.h
index 6e39d54d..c6fe14b8 100644
--- a/include/gwin/options.h
+++ b/include/gwin/options.h
@@ -106,6 +106,17 @@
#define GWIN_BUTTON_LAZY_RELEASE FALSE
#endif
/**
+ * @brief Should the content of the console be logged or not
+ * @details If this feature is enable, the content of the console will be stored.
+ * Every content that gets printed to the console while being invisible
+ * will be rendered once the console is visible again. All previous written
+ * content will be restored too.
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_CONSOLE_HISTORY
+ #define GWIN_NEED_CONSOLE_HISTORY FALSE
+ #endif
+ /**
* @brief Console Windows need floating point support in @p gwinPrintf
* @details Defaults to FALSE
*/
diff --git a/src/gwin/console.c b/src/gwin/console.c
index 7966b6ff..71d46f4f 100644
--- a/src/gwin/console.c
+++ b/src/gwin/console.c
@@ -53,28 +53,68 @@
};
#endif
+#if GWIN_CONSOLE_NEED_HISTORY
+ static void CustomRedraw(GWindowObject *gh) {
+ #define gcw ((GConsoleObject *)gh)
+
+ uint16_t i;
+
+ // loop through buffer and don't add it again
+ gcw->store = FALSE;
+ for (i = 0; i < gcw->last_char; i++) {
+ gwinPutChar(gh, gcw->buffer[i]);
+ }
+ gcw->store = TRUE;
+
+ #undef gcw
+ }
+#endif
+
static void AfterClear(GWindowObject *gh) {
- ((GConsoleObject *)gh)->cx = 0;
- ((GConsoleObject *)gh)->cy = 0;
+ #define gcw ((GConsoleObject *)gh)
+ gcw->cx = 0;
+ gcw->cy = 0;
+
+ #if GWIN_CONSOLE_NEED_HISTORY
+ // issue an overflow, this is some kind
+ // of emptying the buffer
+ gcw->last_char = gcw->size;
+ #endif
+
+ #undef gcw
}
static const gwinVMT consoleVMT = {
- "Console", // The classname
- sizeof(GConsoleObject), // The object size
- 0, // The destroy routine
- 0, // The redraw routine
- AfterClear, // The after-clear routine
+ "Console", // The classname
+ sizeof(GConsoleObject), // The object size
+ 0, // The destroy routine
+ #if GWIN_CONSOLE_NEED_HISTORY
+ CustomRedraw, // The redraw routine (custom)
+ #else
+ 0, // The redraw routine (default)
+ #endif
+ AfterClear, // The after-clear routine
};
GHandle gwinGConsoleCreate(GDisplay *g, GConsoleObject *gc, const GWindowInit *pInit) {
if (!(gc = (GConsoleObject *)_gwindowCreate(g, &gc->g, pInit, &consoleVMT, 0)))
return 0;
+
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
gc->stream.vmt = &GWindowConsoleVMT;
#endif
+
+ #if GWIN_CONSOLE_NEED_HISTORY
+ gc->buffer = 0;
+ gc->size = 0;
+ gc->last_char = 0;
+ #endif
+
gc->cx = 0;
gc->cy = 0;
+
gwinSetVisible((GHandle)gc, pInit->show);
+
return (GHandle)gc;
}
@@ -82,20 +122,72 @@ GHandle gwinGConsoleCreate(GDisplay *g, GConsoleObject *gc, const GWindowInit *p
BaseSequentialStream *gwinConsoleGetStream(GHandle gh) {
if (gh->vmt != &consoleVMT)
return 0;
+
return (BaseSequentialStream *)&(((GConsoleObject *)(gh))->stream);
}
#endif
+#if GWIN_CONSOLE_NEED_HISTORY
+ bool_t gwinConsoleSetBuffer(GHandle gh, void* buffer, size_t size) {
+ #define gcw ((GConsoleObject *)gh)
+
+ uint8_t buf_width, buf_height, fp, fy;
+
+ if (gh->vmt != &consoleVMT)
+ return FALSE;
+
+ // assign buffer or allocate new one
+ if (buffer == 0) {
+ (void)size;
+
+ // calculate buffer size
+ fy = gdispGetFontMetric(gh->font, fontHeight);
+ fp = gdispGetFontMetric(gh->font, fontMinWidth);
+ buf_height = (gh->height / fy);
+ buf_width = (gh->width / fp);
+
+ if ((gcw->buffer = (char*)gfxAlloc(buf_width * buf_height)) == 0)
+ return FALSE;
+ gcw->size = buf_width * buf_height;
+
+ } else {
+
+ if (size <= 0)
+ return FALSE;
+ gcw->buffer = (char*)buffer;
+ gcw->size = size;
+
+ }
+
+ gcw->last_char = 0;
+
+ return TRUE;
+
+ #undef gcw
+ }
+#endif
+
void gwinPutChar(GHandle gh, char c) {
#define gcw ((GConsoleObject *)gh)
uint8_t width, fy, fp;
- if (!gwinGetVisible(gh))
- return;
-
if (gh->vmt != &consoleVMT || !gh->font)
return;
+ #if GWIN_CONSOLE_NEED_HISTORY
+ // buffer overflow check
+ if (gcw->last_char >= gcw->size)
+ gcw->last_char = 0;
+
+ // store new character in buffer
+ if (gcw->store && gcw->buffer != 0)
+ gcw->buffer[gcw->last_char++] = c;
+
+ // only render new character and don't issue a complete redraw (performance...)
+ if (!gwinGetVisible(gh))
+ return;
+ #endif
+
fy = gdispGetFontMetric(gh->font, fontHeight);
fp = gdispGetFontMetric(gh->font, fontCharPadding);
@@ -150,17 +242,11 @@ void gwinPutChar(GHandle gh, char c) {
}
void gwinPutString(GHandle gh, const char *str) {
- if (!gwinGetVisible(gh))
- return;
-
while(*str)
gwinPutChar(gh, *str++);
}
void gwinPutCharArray(GHandle gh, const char *str, size_t n) {
- if (!gwinGetVisible(gh))
- return;
-
while(n--)
gwinPutChar(gh, *str++);
}
@@ -220,9 +306,6 @@ void gwinPrintf(GHandle gh, const char *fmt, ...) {
char tmpbuf[MAX_FILLER + 1];
#endif
- if (!gwinGetVisible(gh))
- return;
-
if (gh->vmt != &consoleVMT || !gh->font)
return;
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index dc9208e8..6b9cb81e 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -251,15 +251,24 @@ void gwinRedraw(GHandle gh) {
#endif
void gwinClear(GHandle gh) {
- if (!((gh->flags & GWIN_FLG_VISIBLE)))
- return;
+ /*
+ * Don't render anything when the window is not visible but
+ * still call the AfterClear() routine as some widgets will
+ * need this to clear internal buffers or similar
+ */
+ if (!((gh->flags & GWIN_FLG_VISIBLE))) {
+ if (gh->vmt->AfterClear)
+ gh->vmt->AfterClear(gh);
+ } else {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
+
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
+ }
}
void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {