| /* |
| * BRLTTY - A background process providing access to the console screen (when in |
| * text mode) for a blind person using a refreshable braille display. |
| * |
| * Copyright (C) 1995-2023 by The BRLTTY Developers. |
| * |
| * BRLTTY comes with ABSOLUTELY NO WARRANTY. |
| * |
| * This is free software, placed under the terms of the |
| * GNU Lesser General Public License, as published by the Free Software |
| * Foundation; either version 2.1 of the License, or (at your option) any |
| * later version. Please see the file LICENSE-LGPL for details. |
| * |
| * Web Page: http://brltty.app/ |
| * |
| * This software is maintained by Dave Mielke <dave@mielke.cc>. |
| */ |
| |
| /* scr.cc - The screen reading library |
| * |
| * Note: Although C++, this code requires no standard C++ library. |
| * This is important as BRLTTY *must not* rely on too many |
| * run-time shared libraries, nor be a huge executable. |
| */ |
| |
| #include "prologue.h" |
| |
| #include "log.h" |
| #include "scr.h" |
| #include "scr_special.h" |
| #include "update.h" |
| #include "message.h" |
| |
| #include "scr_frozen.h" |
| static FrozenScreen frozenScreen; |
| |
| static int |
| frozenScreen_construct (void) { |
| return frozenScreen.construct(&mainScreen.base); |
| } |
| |
| #include "scr_help.h" |
| static HelpScreen helpScreen; |
| |
| static int |
| helpScreen_construct (void) { |
| return helpScreen.construct(); |
| } |
| |
| #include "scr_menu.h" |
| #include "menu_prefs.h" |
| static MenuScreen menuScreen; |
| |
| static int |
| menuScreen_construct (void) { |
| Menu *menu = getPreferencesMenu(); |
| if (!menu) return 0; |
| |
| updateLogMessagesSubmenu(); |
| return menuScreen.construct(menu); |
| } |
| |
| typedef struct { |
| const char *const name; |
| int (*const construct) (void); |
| void (**const destruct) (void); |
| BaseScreen *const base; |
| |
| const unsigned autoDestruct:1; |
| |
| unsigned isConstructed:1; |
| unsigned isActive:1; |
| } SpecialScreenEntry; |
| |
| #define SPECIAL_SCREEN_INITIALIZER(type) \ |
| .name = #type, \ |
| .construct = type ## Screen_construct, \ |
| .destruct = &type ## Screen.destruct, \ |
| .base = &type ## Screen.base |
| |
| static SpecialScreenEntry specialScreenTable[] = { |
| [SCR_FROZEN] = { |
| SPECIAL_SCREEN_INITIALIZER(frozen), |
| .autoDestruct = 1 |
| }, |
| |
| [SCR_HELP] = { |
| SPECIAL_SCREEN_INITIALIZER(help) |
| }, |
| |
| [SCR_MENU] = { |
| SPECIAL_SCREEN_INITIALIZER(menu) |
| }, |
| }; |
| |
| static const unsigned char specialScreenCount = ARRAY_COUNT(specialScreenTable); |
| |
| static SpecialScreenEntry * |
| getSpecialScreenEntry (SpecialScreenType type) { |
| return &specialScreenTable[type]; |
| } |
| |
| static void |
| logScreenAction (const char *type, const char *name, const char *action) { |
| logMessage(LOG_DEBUG, "%s %s screen: %s", action, type, name); |
| } |
| |
| static void |
| logMainScreenAction (const char *action) { |
| logScreenAction("main", screen->definition.name, action); |
| } |
| |
| static void |
| logSpecialScreenAction (const SpecialScreenEntry *sse, const char *action) { |
| logScreenAction("special", sse->name, action); |
| } |
| |
| static int |
| constructSpecialScreen (SpecialScreenEntry *sse) { |
| if (sse->isConstructed) return !sse->autoDestruct; |
| logSpecialScreenAction(sse, "constructing"); |
| if (!sse->construct()) return 0; |
| sse->isConstructed = 1; |
| return 1; |
| } |
| |
| static void |
| destructSpecialScreen (SpecialScreenEntry *sse) { |
| if (sse->isConstructed) { |
| logSpecialScreenAction(sse, "destructing"); |
| (*sse->destruct)(); |
| sse->isConstructed = 0; |
| } |
| } |
| |
| void |
| beginSpecialScreens (void) { |
| initializeFrozenScreen(&frozenScreen); |
| initializeMenuScreen(&menuScreen); |
| initializeHelpScreen(&helpScreen); |
| } |
| |
| void |
| endSpecialScreens (void) { |
| SpecialScreenEntry *sse = specialScreenTable; |
| SpecialScreenEntry *end = sse + specialScreenCount; |
| |
| while (sse < end) { |
| destructSpecialScreen(sse); |
| sse += 1; |
| } |
| } |
| |
| static void |
| announceCurrentScreen (void) { |
| const char *title = currentScreen->getTitle(); |
| if (title) message(NULL, title, 0); |
| } |
| |
| static void |
| setCurrentScreen (BaseScreen *screen) { |
| if (screen != currentScreen) { |
| currentScreen->onBackground(); |
| currentScreen = screen; |
| currentScreen->onForeground(); |
| |
| scheduleUpdate("new screen selected"); |
| announceCurrentScreen(); |
| } |
| } |
| |
| static void |
| setSpecialScreen (const SpecialScreenEntry *sse) { |
| logSpecialScreenAction(sse, "selecting"); |
| setCurrentScreen(sse->base); |
| } |
| |
| static void |
| selectCurrentScreen (void) { |
| const SpecialScreenEntry *sse = specialScreenTable; |
| const SpecialScreenEntry *end = sse + specialScreenCount; |
| |
| while (sse < end) { |
| if (sse->isActive) { |
| setSpecialScreen(sse); |
| return; |
| } |
| |
| sse += 1; |
| } |
| |
| logMainScreenAction("selecting"); |
| setCurrentScreen(&mainScreen.base); |
| } |
| |
| int |
| activateSpecialScreen (SpecialScreenType type) { |
| SpecialScreenEntry *sse = getSpecialScreenEntry(type); |
| |
| if (!constructSpecialScreen(sse)) return 0; |
| logSpecialScreenAction(sse, "activating"); |
| sse->isActive = 1; |
| setSpecialScreen(sse); |
| return 1; |
| } |
| |
| void |
| deactivateSpecialScreen (SpecialScreenType type) { |
| SpecialScreenEntry *sse = getSpecialScreenEntry(type); |
| |
| logSpecialScreenAction(sse, "deactivating"); |
| sse->isActive = 0; |
| if (sse->autoDestruct) destructSpecialScreen(sse); |
| selectCurrentScreen(); |
| } |
| |
| int |
| haveSpecialScreen (SpecialScreenType type) { |
| return getSpecialScreenEntry(type)->isActive; |
| } |
| |
| int |
| isSpecialScreen (SpecialScreenType type) { |
| return currentScreen == getSpecialScreenEntry(type)->base; |
| } |
| |
| int |
| constructHelpScreen (void) { |
| SpecialScreenEntry *sse = getSpecialScreenEntry(SCR_HELP); |
| |
| return constructSpecialScreen(sse); |
| } |
| |
| int |
| addHelpPage (void) { |
| return helpScreen.addPage(); |
| } |
| |
| unsigned int |
| getHelpPageCount (void) { |
| return helpScreen.getPageCount(); |
| } |
| |
| unsigned int |
| getHelpPageNumber (void) { |
| return helpScreen.getPageNumber(); |
| } |
| |
| int |
| setHelpPageNumber (unsigned int number) { |
| return helpScreen.setPageNumber(number); |
| } |
| |
| int |
| clearHelpPage (void) { |
| return helpScreen.clearPage(); |
| } |
| |
| int |
| addHelpLine (const wchar_t *characters) { |
| return helpScreen.addLine(characters); |
| } |
| |
| unsigned int |
| getHelpLineCount (void) { |
| return helpScreen.getLineCount(); |
| } |