diff --git a/include/gint/gray.h b/include/gint/gray.h index d488fd4..9443a73 100644 --- a/include/gint/gray.h +++ b/include/gint/gray.h @@ -43,12 +43,11 @@ enum { When functions that use the gray engine call functions that don't and vice- versa, it can be tedious to know exacly when the gray engine should be - running. This function provides a stack of gray engine states to solve this - problem. When entering a function that uses/doesn't use the gray engine, you - can call dgray(DGRAY_PUSH_ON)/dgray(DGRAY_PUSH_OFF) to start/stop the - engine; then call dgray(DGRAY_POP) at the end of the function. - dgray(DGRAY_POP) will restore the state of the engine as it was before the - previous DGRAY_PUSH_*. This allows each function to set its own state + running. To solve this problem, this function provides DGRAY_PUSH_ON and + DGRAY_PUSH_OFF that save the current state of the engine before starting or + stopping it. DGRAY_POP can later be used to transition back to the saved + state. 32 states can be saved, meaning that up to 32 DGRAY_PUSH_* can be in + effect simultaneously. This allows each function to set its own state without altering the state of their callers. This function returns non-zero if the engine has failed to initialize at diff --git a/src/gray/engine.c b/src/gray/engine.c index 42d6c9a..e589684 100644 --- a/src/gray/engine.c +++ b/src/gray/engine.c @@ -148,25 +148,49 @@ static void gray_stop(void) /* dgray(): Start or stop the gray engine at the next dupdate() */ int dgray(int mode) { + /* Stack of states for the push modes */ + static uint8_t states[32] = { 0 }; + static uint8_t current = 0; + if(mode == DGRAY_ON) { if(!gray_isinit()) return 1; /* Set the display module's alternate rendering mode to override rendering functions to use their g*() variant */ - dmode = &gray_mode; - return 0; + if(!dgray_enabled()) dmode = &gray_mode; } else if(mode == DGRAY_OFF) { /* Set the mode to a temporary one that only overrides dupdate() so that we can stop the engine next frame */ - if(dmode == &gray_mode) dmode = &gray_exit_mode; - return 0; + if(dgray_enabled()) dmode = &gray_exit_mode; } + else if(mode == DGRAY_PUSH_ON) + { + if(current >= 32) return 1; + states[current++] = dgray_enabled() ? DGRAY_ON : DGRAY_OFF; - /* TODO: DGRAY_PUSH_* and DGRAY_POP */ - return 2; + return dgray(DGRAY_ON); + } + else if(mode == DGRAY_PUSH_OFF) + { + if(current >= 32) return 1; + states[current++] = dgray_enabled() ? DGRAY_ON : DGRAY_OFF; + + return dgray(DGRAY_OFF); + } + else if(mode == DGRAY_POP) + { + /* Stay at 0 if the user's push/pop logic is broken */ + if(current > 0) current--; + + /* Switch to previous state */ + return dgray(states[current]); + } + else return 1; + + return 0; } /* gray_int(): Interrupt handler */