first implementation of console buffer. This has to be tested first - might contain bugs
This commit is contained in:
parent
92750f0207
commit
aa2f7585ce
4 changed files with 147 additions and 21 deletions
|
@ -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
|
||||
|
|
|
@ -105,6 +105,17 @@
|
|||
#ifndef GWIN_BUTTON_LAZY_RELEASE
|
||||
#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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue